AI opponents that play like people, not optimizers¶
The first time my eight-year-old beat a board game AI, she didn't celebrate. She frowned and said "the computer wasn't trying."
She was right. The AI was trying very hard -- it was running 800 Monte Carlo rollouts per move and picking the statistically optimal action -- but it didn't feel like it was trying. It felt like a vending machine. You put in a turn, you got out an answer. There was no person on the other side. There was no opponent. There was just a fact.
I'd spent two months getting that AI to win consistently and somehow ended up with the worst opponent in the house.
The optimizer is the wrong opponent¶
There's a default assumption in game-AI work that goes something like: the harder it is to beat, the better the AI is. Difficulty sliders. ELO ratings. Hard / Medium / Easy modes. The whole framing treats AI quality as a one-dimensional optimization: how often does it win?
That framing is a hangover from chess engines, where the customer was a chess player who wanted a sparring partner of a specific strength. Stockfish at 2400 ELO is a fair fight for someone rated 2400. The game doesn't need a personality because the human supplies the personality on their end of the board.
Family board game night is not chess. The customer is a household of mixed ages and skill levels who want to play together for an hour. An AI that wins 50% of the time against the strongest player wins 100% of the time against the weakest, and the kid who never wins stops wanting to play. An AI that's tuned down to win only 20% of the time against the strongest player is a pushover for everyone else and the strongest player is bored. Every "difficulty slider" solution to this is a compromise that fails everyone simultaneously.
The right axis isn't difficulty. It's who is this opponent?
Three personalities¶
This project has three AI personalities. None of them have a difficulty slider. They each play differently because they each are different.
Steady Eddie¶
Eddie runs a clean Monte Carlo Tree Search at 400 simulations per move and picks the move with the most visits. (Monte Carlo Tree Search, or MCTS, just means the computer plays out hundreds of random versions of the rest of the game in its head and favors the move that won the most of those imagined games -- no hand-written strategy, only counting which move tends to work out.) That's it. No theatrics. He's the calibration baseline -- the opponent who plays the right move when there is one, doesn't fall for tricks, and doesn't try to surprise you.
What Eddie doesn't do is interesting. He doesn't bluff. He doesn't sandbag. He doesn't go for risky high-variance plays when he's behind. If you're winning, Eddie acknowledges it by quietly trying to win and failing. If you're losing, Eddie acknowledges it by quietly winning. He's the opponent who shows up on time, plays a solid game, and shakes your hand.
Eddie is the AI for "I want to play a game where the computer doesn't suck." He's not exciting. That's a feature. Half the time you don't want the computer to be a character -- you want it to play, well, steadily.
The Prodigy¶
The Prodigy runs MCTS at 800 simulations per move -- twice Eddie's compute budget -- and is, on paper, the strongest AI in the lineup. He's also the most likely to lose to a clever human, and that's by design.
The trick is a parameter called BOREDOM_RATE, set to 0.10. After MCTS finishes its search, The Prodigy looks at the top two moves by visit count. Ten percent of the time, instead of playing the best move, he plays the second-best move.
The visible behavior: he sometimes makes inexplicable choices that look brilliant in retrospect or disastrous in retrospect, and you can never tell which until later. He plays moves that no statistically rational opponent would play. Sometimes those moves throw the game. Sometimes those moves were three steps ahead of where you thought the game was, and now you're behind.
The Prodigy is not the strongest opponent. He's the most interesting opponent. He's the AI for "I want a game where I might lose to something I didn't see coming."
Old Reliable¶
Old Reliable runs MCTS at 150 simulations per move -- much less than Eddie. He's the weakest AI by raw search depth. But he has a different parameter: TEACHABLE_SKIP_RATE, set to 0.5.
Here's what that does. After MCTS picks a move, Old Reliable checks: did the search find any moves that block an immediate win by my opponent If yes, and the dice roll comes up under 0.5, he ignores those blocking moves and picks something else.
Translated: half the time, when you have a winning move on the board, Old Reliable lets you take it. He does not see the threat. He does not block the four-in-a-row. He does not stop the rush.
(The four-in-a-row here is Connect Four, which is the project's internal proving engine: it has a real game engine under the relevant engine module that the AI is exercised against, but no player-facing stage UI yet. It is where blocking behavior gets demonstrated, not a game on the family catalog you can sit a kid down in front of today.)
This sounds like a bug. It is the most popular AI in the lineup with families.
The reason: Old Reliable is the opponent for kids learning to play. When a six-year-old finally sees the winning move, Old Reliable lets them take it about half the time. The other half, he does block -- so it's not a giveaway, it's a teachable game. The kid wins enough to stay engaged and loses enough to keep learning. The grown-ups can let the kid play against Old Reliable without it feeling rigged because, mechanically, it isn't -- Old Reliable is a real opponent who happens to have a real flaw, and the flaw is age-appropriate for the customer.
These three are the base personality set -- they share one MCTS core, so they slot into the same turn-based games. They are not reused verbatim across the whole catalog, though. What recurs is the pattern -- personality over difficulty -- not the exact roster. Each game ships its own set tuned to its mechanics: Bluff has Honest Eddie, Liar Larry, and Paranoid Pat in the relevant AI module, and Texas Hold'em has the TAG, LAG, Nit, Calling Station, and Maniac archetypes in the relevant AI module. The idea travels game to game; the named characters are per-game.
Every move gets graded¶
The other half of "AI as a person" is what happens after a move, not during it.
Borrowing wholesale from chess.com: every move in every game gets tagged with one of five qualities -- BRILLIANT, GOOD, INACCURACY, MISTAKE, or BLUNDER. The tags come from a comparison between the move played and the move MCTS would have picked, weighted by how much the position changed.
The tags are visible during play (small icons next to the move log) and central to the post-game review screen. After the game ends, you can scroll through every move, see what was graded what, and -- if you want -- get an explanation of why a move was a blunder.
This is the loop. Not "did you win?" The loop is "what did you learn?" Chess.com figured out years ago that the post-game review is more valuable than the game itself, because the game is forgettable but the review is memorable. Family board game night has the same structure: the game is the social event, the review is what makes you better next time.
Why personalities, not difficulty¶
If you want a Hard mode, set The Prodigy's BOREDOM_RATE to 0 and crank his simulations to 2000. You'll have an unbeatable opponent. Nobody plays against that opponent twice.
If you want an Easy mode, set Eddie's simulations to 50. You'll have a terrible opponent who plays randomly. Nobody plays against that opponent twice either.
The Hard / Easy framing creates two bad games. The personalities framing creates three different games -- Eddie's game (a calibration check), The Prodigy's game (a riddle), Old Reliable's game (a teaching tool) -- and each of them is the right game for a specific moment in family life. Game night with the in-laws -> Eddie. Just-the-grown-ups after the kids are asleep -> The Prodigy. Six-year-old learning the ropes -> Old Reliable. Same engine, same MCTS, same five-quality move grading. Different personalities, different experiences.
The harder problem isn't beating the human. It's being someone the human wants to play with.