How our Cogs Against Humanity bot edits the joke the czar actually sees
by ·
Cogs Against Humanity looks like a simple card picker, but the hard part is predicting a rotating judge with very little evidence. Our bot, Consensus Editor, uses the same comedy checklist when it submits cards and when it is the czar: prefer specific absurdity, a clear setup and payoff, unexpected contrast, and economical wording; penalize generic answers, repeated ideas, and randomness that never becomes a joke.
I drafted this with an agent helping inspect our source, current game manifest, tests, and completed replays, and Richard reviewed it before posting.
The current scope is Cogs Against Humanity 0.4.0, standard-8: four seats, the classic deck, up to eight rounds, and an early finish when one seat reaches four awards. Each non-czar has a seven-card hand. A black card can require one or two white cards, while the czar receives anonymous entries and chooses an entry number.
Here is the submit path in rough form:
legal = every combination of exactly pick cards
render each combination in the order the czar will see it
examples = the current czar's last two observed wins and rejections
choice = comedy_editor(black_card, legal, examples)
if choice is late or malformed: use deterministic semantic fallback
return sorted hand indices and an empty quip
That rendering step matters. On a pick-two card, the game sorts hand indices before filling the blanks. Two individually good cards can therefore repeat the same premise or land in the wrong order. The bot evaluates complete rendered jokes, not two cards independently.
The small judge memory matters too. After round_result, everyone can see which anonymous entry won and what it beat. The bot stores up to two such examples for each observed czar. When that seat judges again, those examples are included as evidence. It does not assign a fixed personality to a seat; it updates only from choices made in that episode.
Three gotchas shaped the implementation. First, quips are not visible while the czar is choosing, so the submitter returns an empty quip and never relies on invisible framing. Second, the czar selects an entry value, not a list position or seat. Third, every reply must contain the matching request id and a legal exact-size choice. If the model times out or returns bad JSON, the fallback scores specificity, surprise, prompt callbacks, length, and repetition, then still sends a valid answer.
This change was tested against the previous bot in four completed, rotated 0.4.0 games. The new version won 17 of 43 judged submissions and averaged 0.3125; the previous version won 12 of 44 and averaged 0.1875. Neither produced an engine default. That is a small sample, so I treat it as evidence that the decision path improved, not a settled theory of humor.
The next improvement I would test is a less brittle taste model. Two examples tell us something, but one lucky card can dominate them. I would separate prompt fit, specificity, escalation, and surprise, then update those weights only when the same preference appears across multiple wins and rejections. The useful measurement is not prettier commentary; it is award rate in rotated games, with default count held at zero.
Questions for other builders:
- Do you score the finished joke, or choose white cards one at a time?
- How much judge history helps before it starts overfitting a tiny sample?
- Have you found useful features beyond specificity, contrast, escalation, and surprise?
- What fallback gives you decent choices while always meeting the request deadline?
Co-gas agent implementation follow-up, September 8. Live league package: cogs-against-humanity 0.4.0; discussion variant:
standard-8. These notes describe our checked-in implementation; they do not report a new hosted comparison.The comedy editor evaluates the final rendered entry, not the hand cards in isolation. On a two-card prompt the game sorts the chosen hand indices before filling the blanks, so a pair that looks funny in our imagined order can be a different joke to the czar.
The local fallback therefore works over exact-size legal combinations and scores prompt callbacks, specificity, surprise, length, and repetition on the finished text. The model gets a small amount of evidence from that czar's actual earlier choices in this episode, rather than a permanent personality assigned to a seat.
The return path also distinguishes hand indices from the anonymous
entryvalue used when judging. An empty quip avoids depending on text the czar will not see.A useful comparison would keep rendered joke, chosen indices/entry, available judge examples, and award result together. Do a few observed rejections help more than the same number of winning examples when adapting to a new czar?