Skip to content
campbellsoup37 edited this page Dec 23, 2025 · 6 revisions

AI Strategy Modules

Every robot player has an attached strategy module that it consults for all bidding and playing decisions. More concretely, the strategy module is an object whose class extends the abstract class AiStrategyModule and (at least) overrides the functions makeBid() and makePlay(). These functions are allowed to collect and process information about the game and must execute a bid or card play, respectively, on behalf of the player. The intention is for the strategy module to contain all logic relevant to that strategy, making it relatively easy to implement different strategies and test them out, potentially against each other.

Part of my goal for this Oh Hell project is for everything to be done from scratch. So, all of the machine learning is in the Java. General machine learning tools, including neural network models, layers, vectors, matrices, activation functions, loss functions, and some other things like decision trees, bagging models, and gradient boosting models can be found in the ml package. Code that uses these tools for training AI can be found in the aiworkshop package, and the strategy modules themselves can be found in their own packages (e.g., the OI module is in strategyOI).

OI module

Overview

Currently, the default (and most successful) strategy module is the OI module (stands for Overall-Immediate). A high level explanation of the underlying approach to bidding and playing is:

  1. always bid the number that will maximize the expected points, and
  2. always play the card that will maximize the probability of making the bid.

The strategy module tries to accomplish these tasks by estimating and utilizing the following probabilities.

  • Given a card $c$, define the overall value of $c$, denoted $p_O(c)$, to be the probability that will win a trick at some point in the remainder of the round.
  • Given a card , define the immediate value of , denoted , to be the probability that will win the current trick.

Note that there are more conditions on these probabilities, i.e., and take more inputs than just the card . For instance, it is important what the other players' bids are, what cards have already been played, what the trump suit is, etc. The strategy module estimates overall and immediate values with neural networks, as described in the next section. But, to finish off the overview, I'll now describe how the overall and immediate values of cards can be used to estimate the quantities relevant in (1) and (2).

Suppose our hand has cards

.

Consider some subset of of size . The probability that the cards in all win tricks at some point in the round and the cards not in all lose tricks is

,

where means the product is over all cards in and means the cards in not in (note that this assumes the events are independent, which in reality is almost certainly false, but it is a good enough approximation). Going further, given a number , the probability that we will make exactly tricks is the product of the numbers , where ranges over subsets of size .
  1. Suppose it's our turn to bid. Given a number , the expected number of points we will make by bidding is

,

where denotes the number of points gotten by bidding and taking tricks.
  1. Suppose it's out turn to play a card and that we still want tricks. Given a card in our hand , the probability we will make exactly tricks from now until the end of the round if we play is

by the law of total probability.

Neural networks

The OI module uses two neural networks that estimate overall value and immediate value. They are called OVL (overall value learner) and IVL (immediate value learner) respectively. An OVL-IVL pair is trained for a specific number of players and decks. For the remainder of this section, we will consider the number of players and the number of decks (either 1 or 2) fixed. We also define the quantity , which is the maximum hand size. Lastly, will always denote a card in hand.

OVL

The features and dimensions for the input layer of the OVL are listed below. They are all discrete and encoded as one-hots.

Feature Dimension
Cards left in hand
Tricks still wanted (one vector for each player)
Number of voids in hand
Trump not seen
is or is not trump
Cards not seen in 's suit
's adjusted number (explained below)
's matching copies not seen

's adjusted number is a modified version of 's number that is meant to account for cards already seen (i.e., already played, in hand, or as the flipped up trump card). It can be defined as the number of cards in 's suit that will beat plus the number of seen cards that would beat . For this reason, the OVL (and IVL) will treat consecutive cards in hand as equivalent in a single-deck game.

The output of the OVL is a single value between 0 and 1 estimating . The final activation function is sigmoid, and all others are ReLU.

IVL

To estimate , the OI module first checks if it can definitively say . For instance, this is the case when is not trump and its suit is not the led suit. In single-deck, this is also the case when is beaten by a card already in the trick. In double-deck, it's more complicated. If is trump or its suit is the led suit, then the OI module first determines the number of cancels that need to occur among cards already in the trick for to have a chance of winning. If this number is greater than the number of players who have yet to play, then again we can say . If none of these checks pass, then the OI module resorts to the IVL.

The features and dimensions for the input layer of the IVL are listed below. Again, they are all discrete and encoded as one-hots.

Feature Dimension
Tricks still wanted (one vector for each player)
Trump not seen
Trump was led
Cards not seen in led suit
is or is not trump
Cards not seen in 's suit
's adjusted number (see above)
's matching copies not seen
Cancels required (see above) 0 if , if

The output of the IVL is a single value between 0 and 1 estimating . Again, the final activation function is sigmoid, and all others are ReLU.

Hyperparameters and training

The OVL and IVL are put into an OI module and are trained together on many games. AI players are put in a game, all hooked up to this same OI module and feeding data into its OVL and IVL. Since the OVL and IVL are estimating conditional probabilities of a card winning tricks, the "truth" values of these probabilities are set to 1 or 0 depending on whether that card did or did not win the trick respectively. The data used per epoch is always the data coming from some number of full games.

I have trained OVLs and IVLs typically with only one hidden layer. The number of dimensions of the hidden layer is usually set to 40 for OVL and 30 for IVL, though they seem to reach similar accuracy with hidden layer dimensions as low as 10 or even 5.

As the OVL and IVL train, I monitor the performance of the OI module in terms of its average score and the mean squared error of the OVL and IVL. I manually adjust the learning rate and amount of data per epoch accordingly, in between epochs. As learning stagnates, I decrease the learning rate and increases the amount of data per epoch to decreases variance. For and , the OI module usually reaches a competent level of play after around 1000 games.

Clone this wiki locally