Three games from the tea house
دۆمینە · ئۆکەی · کۆنکان
The games actually played over tea in Erbil, rather than the ones a portfolio usually reaches for. All three are folk games, so the rules vary by house — each one states the variant it implements.
Tap a tile to play it; if it fits both ends you get to choose which, because that choice is the game. Tiles you cannot use are dimmed. If nothing fits, draw — and when the boneyard is empty, pass.
The problemMost games of domino do not end with somebody going out
Everybody implements “first to play all their tiles wins” and stops there. But a large share of real games end blocked — tiles still in both hands, and neither player able to move. If that case is not handled the game simply hangs, and the two people at the table look at each other.
Blocked is not an edge case in domino, it is an ordinary ending, so it needs a rule rather than a crash: two consecutive passes finish the hand, and whoever is holding fewer pips takes it. The pip count is on screen for exactly that reason.
The opponent plays its heaviest legal tile. That is a real strategy rather than a good one, and the note is here so the demo does not imply more intelligence than it has.
Draw a tile, then tap one to discard. The star tiles are wildcards. Play passes to your left, and each seat may take the discard of whoever played just before it — which for you is Right. The row under the rack is the search running live: how many of your fourteen it can group at this moment, and which groups those are.
The problemDeciding whether a hand has won
The other three seats are played rather than drawn. They hold real tiles, take a discard when it improves their hand, throw whatever the search can do least with, and go out before you often enough to make the hand worth hurrying. They are scored by the same function your own rack is scored by — which is the only opponent worth writing when the search is already there.
And that search is where the interesting part is. The obvious way to check a hand is greedy: find the longest run, take it, repeat with what is left. It is wrong, and it is wrong in the worst way — it looks right most of the time.
Take a hand of green 1–7, a red 4 and a blue 4, and black 1–5. Greedy grabs the green 1–7 because it is the longest run, then the black 1–5, and is left holding two fours it can do nothing with. It reports the hand as incomplete.
The hand does win — but only by breaking the green run in two, so the green 4 is free to join the red and blue ones as a set. Greedy cannot find that, because it never reconsiders a group it has already taken. Here is the same hand, split by the same function the game uses:
So the check is an exhaustive search with memoisation: take the lowest remaining tile, try every group that could contain it, recurse on the rest. Exponential in principle; for fourteen tiles it finishes in well under a millisecond, which is the whole reason it is safe to run it on every single change.
Wildcards make it harder rather than easier: they can stand for any tile, so every branch has to try spending one as well as not. A leftover wildcard is not a win either — every tile has to belong somewhere.
Draw or take the discard, then tap a card to throw it away. Jokers stand in for anything. Your opponent is doing the same thing on the other side of the table — if they get there first, they win. The row underneath is the same search as Okey, running on every change.
The problemThe same question, wearing a different suit
Konkan asks the identical question to Okey: can these fourteen be partitioned into sets and runs? So it does not get its own algorithm. The cards are translated into the same shape the Okey checker expects — a suit behaves exactly like a colour — and the search runs unchanged.
That is the whole reason the checker takes an abstract
{colour, number} rather than anything that knows what a
tile or a card is. Two games, one search, and a bug fixed in one is
fixed in both.
Jokers here are true wildcards rather than a named tile, which is the one real difference from Okey — and it costs nothing, because the search already had to handle spending a wildcard on any branch.
The opponent is the same search again, pointed the other way: it takes your discard only when the search says its hand improves, and throws whatever the search can do least with. Nothing about it peeks at your cards.