Build a Mahjong AI
Mahjong is a traditional Chinese gambling game played throughout Asia in which four players draw and discard tiles in order to try to complete a hand of 14 tiles.
In this problem, a specification for a simplified version of Mahjong called "PPCG Mahjong" was given. Your task in this problem is to build a program that will play a version defined here called "Full PPCG Mahjong" (hereafter known as the FPM rules).
Your program will be an online program, taking input as it plays the game. (that does not necessarily mean it needs networking capabilities, but it means that it will output in reaction to ongoing input, not just all input at once.)
There are 34 types of tiles in FPM.
The “bǐng”/“pin” (餅) tiles, also known as the circle tiles / dot tiles. These will be represented in text with a number from
9 and then the letter
b, as in
2b, up to
The “suǒ”/“sou” (索) tiles, also known as the bamboo tiles. These will be represented in text with a number from
9 and then the letter
s, as in
2s, up to
The “wàn”/“man” (萬) tiles, also known as the character tiles. These will be represented in text with a number from
9 and then the letter
w, as in
2w, up to
The three tile types totalling 27 tiles above are called the number tiles.
The “fēng”/”fuu” (風) tiles, also known as the wind tiles. There is one wind tile for each cardinal direction. These will be represented in text with the letter of the wind's cardinal direction in capitals, repeated twice, as in:
The “yuán”/“gen” (元) tiles, also known as the dragon tiles. There is one red, one green, and one white dragon, represented as
ZZ (for zhōng 中/center),
FF (for fā 發/fortune), and
BB (for bái 白/white) respectively.
The two tile types above are called the honour tiles. There are four of each type of tile, for a total of 136 tiles.
The goal of Mahjong is to form a complete hand, which consists of four sets and a pair.
A set is one of:
A sequence of number tiles. (e.g.
5w 6w 7w or
3s 4s 5s)
A triplet of any tile (number or honour tile). (e.g.
3b 3b 3b or
EE EE EE)
A quadruplet of any tile. (e.g.
3b 3b 3b 3b or
EE EE EE EE)
A complete hand will have 14 tiles if there are no quadruplets present; each quadruplet adds one tile to the hand's size, up to a possible 18.
Mahjong is a game played in several hands (局, jú).
At the beginning of each hand, each player receives a text input of
START [Wind] [Round number]. Each player is then given an input of 13 tiles, represented as a set of 13 space-separated strings (e.g.
1b 9s BB 3w 6w 4b ZZ 3w 5w 2s 6b NN NN) and assigned a different seat wind depending on where they "sit" at the virtual table (given as a single letter out of
Starting with the player at position East and moving clockwise around the compass, each player takes a turn in which:
The player whose turn it is will be given a tile (自摸牌, zìmōpái) from the "wall" (the collection of tiles that have not been drawn or dealt yet) as a two-character input.
The player can take actions during the standby phase:
If the player has four of the same tile in his hand, it can call kong (槓, gàng) and draw an extra tile. Those tiles must stay as a quadruplet from then on and cannot be used for anything else. The program does this by outputting
kong [quadruplet tile] as text.
If the player previously called pung on a triplet and has a fourth of the tile, it can call kong as well.
If the player's hand is complete with this drawn tile, it may declare hu in which case the hand ends.
The player will then produce an output of whatever tile it decides to discard. The tile that was discarded will be propagated as output to the other players in the form
[seat] [discarded tile] (e.g.
E 8w). The players can then call that tile if it will complete a set:
The player immediately after the discarding player may call chi (吃, chī) by outputting
chi as text during the call phase, to complete a sequence.
Any other player can call pung (碰, pèng) to complete a triplet, similarly by outputting
pung as text. Pung overrides chi when it happens.
Any player can also call kong (槓, gàng) to complete a quadruplet, also by outputting text, in which case they are given an extra tile as text input.
Any player can also call hu (胡, hú) to complete their hand regardless of whether they are completing a sequence, triplet, or pair. Hu overrides both pung/kong and chi.
If a player does not want to call tiles, it must output
The turn immediately goes to the player who called the tile, and they skip their draw phase, discarding another tile immediately. If nobody called a tile, the next player draws one. At any point if a player calls, the other three players will receive an input indicating that the player in that seat made a call and what was called.
For chi, the input will be in the form of
[seat] chi [other two tiles] (e.g.
S chi 6w 7w).
For pung and kong, the input will be in the form of
[seat] pung/kong. This is because all the tiles are identical to the called tile anyway.
For hu, the input will be in the form of
[seat] hu [all other tiles in hand].
In the above three cases, the tile being called is always the previously discarded tile.
For a kong during the standby phase, the input will be in the form of
[seat] kong [kong tile], because the kong tile is not implied to be the previously discarded tile.
For a hu during the standby phase, the input will be in the form of
[seat] hu [tile drawn]
Once a tile is called, the set that it makes is locked in place and cannot change for the rest of the hand. So if two tiles would make use of a tile in a called set, they may not use that tile.
A hand ends when either somebody calls hu validly or there are no more tiles to draw. (There is no dead wall in this game.) At that point, all players will receive an input of
END to signal that the round has ended, and a summary of their points.
If somebody other than the dealer won, then the deal rotates. If the dealer or nobody won, then the deal stays the same. After four deal rotations, the prevailing wind also rotates.
A game of FPM consists of 16 such deal-rotations (rounds), such that each player gets to play one round with each combination of seat wind and table wind. Each player starts with a bank of 500 points. At the end of 16 rounds, the player with the most points is the winner of the game.
Example gameplay interaction
> START HAND EAST 1
> 1b 4b 6b 2s 9s 3w 3w 5w 6w NN NN ZZ BB
> E // The player is East (dealer)
> NN // East drew the north-wind first.
BB // East decides to discard the white-dragon.
> S 3w // Nobody called it, and South discards a 3-character.
pung // East wants to pung the 3w tile.
ZZ // East discards the red-dragon
> S pung // South pungs the red-dragon.
> S 6w // South discards a 6-character instead.
pass // East has no use for this tile, so it passes.
> W kong 2s // West declares a standby kong on 2-bamboo.
> W 3b // West discards a 3-circle.
pass // East passes again.
> N chi 2b 4b // North chi-s it with a 2b and 4b.
> N 7s // North discards a 7-bamboo.
> 2w // East's hand: 1b 4b 6b 2s 9s 2w 5w 6w NN NN NN -- 3w 3w 3w
2w // East doesn't need the 2w, so he discards it.
> S hu 2b 3b 4b 7s 8s 9s 2w 6w 7w 8w ZZ ZZ ZZ
// South wins on that tile. The 2w completed his pair.
> 496 506 499 499 // Their current point counts. South's hand was worth
// 2 points, so East pays 4 while the others pay 1.
> START EAST 2
> [13 more tiles]
> N // The deal rotated, and this player is now North.
Your program can participate in one of three levels of gameplay:
Level 1, where every hand is worth exactly 8 points, and the only thing that matters is completing hands.
Level 2, where every hand is worth the number of points in the points table section below, but any hand can still win.
Level 3, where every hand is worth the number of points in the points table, but a hand must have at least 8 points total with that system to win.
The following are invalid moves:
Failing to produce an output when required.
Discarding a tile that is not in your hand, or when it is not your turn.
Calling chi on any player other than the one immediately before you, or calling any tile that does not actually complete a set in your hand.
Calling hu when your hand is not complete, or when your hand value does not meet the minimum point requirement in level 3 gameplay.
If your program makes an invalid move, the move will be rejected, your program will pay 20 points to each of the three other players, and for the rest of that round, it will be a "forced tsumogiri" player, which automatically discards every tile it draws and never calls anything.
There are no special rules such as dora or furiten in FPM. Any person may complete a hand at any time as long as it is a valid complete hand.