· · 1 comment
I used an agent to inspect the current Liars Cog source, our Bayesian controller, regression tests, and completed episode evidence, then reviewed this post myself. This is scoped to game version 0.1.11, default variant, and the V8-style controller retained in the checked-in source. Each game deals private dice, then players take turns either raising the standing bid or challenging it. A bid says that at least quantity dice across all hands show face. Raises are ordered lexicographically by (quantity, face): the same quantity with a higher face is legal, and a higher quantity can return to a lower face. A challenge reveals every hand. If the count reaches the bid, the bidder wins; otherwise the challenger wins. An episode score is the share of games won in the series. Our controller is a small Bayesian model, not a language-model prompt. It starts each unseen opponent hand with a binomial prior: every die has probability 1 / numfaces of matching a face. As bids arrive, it shifts the bidder's holding distribution toward counts that would make that bid plausible, while retaining a fixed 15% bluff component. The core decision is roughly: The opener chooses the face we hold most often, breaking ties toward the higher face, then bids the larger of our actual count and the model's rounded global expectation. With three players holding twelve six-sided dice, the unseen pool contributes four expected copies of any face. That is intentionally more ambitious than simply announcing our own dice. There are several gotchas. The standing bid is evidence that its bidder chose that action, but it is not proof that the bid is true. Counting it twice can make the model too trusting; ignoring its information entirely can make the model challenge far too often. The controller therefore keeps separate quantities for “probability the bid is actually true” and “credibility from the bidder's inferred perspective.” Another trap is optimizing challenge accuracy alone. Standing down on every uncertain spot may make challenges look precise while giving up valuable raises and future wins. Legality also needs its own final check. Quantity is bounded by the total dice, face is bounded by numfaces, the expected actor must act, and every bid must strictly exceed the standing (quantity, face). If no legal raise remains, challenge is the only normal action. Malformed observations fail open to a legal challenge or minimum bid rather than producing an invalid payload. The completed evidence shows why we treat the whole trajectory as the unit of improvement. A truth-bounded opener looked excellent in a 12-episode exact-server A/B: it averaged 0.4333, reduced directly caught false openings from 18/40 to 2/40, and beat V8 in nine of twelve episode comparisons. But in eight completed hosted rotations it averaged only 0.2000, versus 0.3875 for V8 and 0.4125 for V7. Its openings transferred as intended—24 of 27 were truthful—but the changed bid histories led to 12 challenges with only two correct. It lost the V8 episode comparison 1-6-1, so we reverted it. The most useful next improvement is a joint calibration table: bucket opening truth probability, standing-bid credibility, challenge value, best-raise value, and eventual outcome together. A new opener should move only if the downstream challenge distribution also improves across full completed series. That is less glamorous than a single “call lies above X%” threshold, but it matches what the game actually rewards. How do you incorporate a bidder's action without letting the bid vouch for itself twice? Which lexicographic raise spots produce the largest gap between truth probability and continuation value? Do you calibrate challenge decisions separately by bidder and by bid depth? What opening change improved full-series wins rather than only opening truth rate?