Third Devvit pilot, and the one where the coach has the least to apologise for. Fibbers Dice is Liar’s Dice: everyone hides five dice under a cup, bids on how many of a face are on the whole table, and the round ends when somebody calls the bluff. The maths of that is exactly computable, which is not true of most games in the hub.
What It Is
A Devvit Web app on r/wanessalabsdev. A moderator creates the post and the post is the table: two, three or four players holding five dice each, ones wild, bids that may only go up in quantity or in face.
You bid by tapping a cell in a six-column grid rather than nudging two counters. Every cell that would be an illegal bid is inert, so the rule that a bid must exceed the last one is enforced by the layout rather than by an error message. Then you either raise, call the bluff, or claim the count is exactly right.
The Coach Is Exact Here
The panel reports one number and it is a real calculation: the probability that at least the needed quantity is on the table, given what is under your own cup and how many dice you cannot see.
binomialAtLeast(unknownDice, needed, matchChance(face, publicView))
matchChance is where the wild ones go, so the probability of a die matching a bid on face four is not one in six. The function comes from src/games/fibbers-dice/bots/probability in the hub, and a test pins its output against hand-computed values with wilds included. Nothing is sampled and nothing is approximated.
The Meter Rates the Claim, Not the Player
The bluff thermometer runs 5 to 95 and starts at 100 - claimOdds, then adjusts for the bidder’s personality: a maniac reads hotter, a tight player colder. So it is not reading their dice and it is not reading their behaviour. It is telling you how unlikely the thing they just said is, from where you sit, which is the number a player should be forming anyway and usually is not.
That makes it a different instrument from the poker pilot’s meter, which resolves the opponent’s actual hand. This one only ever knows what you know.
The Seed Is the Post, With One Honest Caveat
derivePostSeed(postId) feeds the hub’s seededRandom, and that draws both the opponent roster and the opening cups for every seat. Everyone reading the same post starts from the same table against the same three characters.
A restart does not. restartMatch rolls fresh dice from Math.random, so a second attempt in the same post is not the daily hand any more, and the thread leaderboard cannot tell the difference. Worth knowing before reading too much into a top score.
One Engine, Two Surfaces
| Piece | Role |
|---|---|
devvit.json | Manifest: post entrypoint, server bundle, subreddit menu item |
src/server/index.ts | Express on @devvit/web/server. Create post, /api/init, /api/submit-score |
| Devvit Redis | zAdd / zRange on lb:fibbers:{postId}, namespaced rather than bare like the first two pilots |
FibbersDiceView.tsx | The table: cups, SVG dice, the bid grid, the coach panel, the meter, the action log |
Scoring is a base of 1000 plus 200 for every die you still hold, with 300 more for catching a pure bluff and a bonus for calling the count exactly. Three tests cover the parts that fail quietly: seed determinism, the binomial with wilds, and who wins a challenge.
Constraints
Same sandbox rules as the first two pilots: no coin economy, no Supporter Pack, no external network calls, no localStorage. Anything that persists is held by Reddit. Two build bundles, Vite for the webview and esbuild into a single CommonJS file for the server.