mirror of
https://github.com/correl/riichi.git
synced 2024-11-23 19:19:55 +00:00
More yaku
This commit is contained in:
parent
d4157e3aa2
commit
37e3a21b75
2 changed files with 118 additions and 2 deletions
64
src/yaku.erl
64
src/yaku.erl
|
@ -20,6 +20,12 @@
|
|||
san_kan_tsu/2,
|
||||
toi_toi/2,
|
||||
san_an_kou/2,
|
||||
shou_san_gen/2,
|
||||
honrouto/2,
|
||||
honitsu/2,
|
||||
jun_chan/2,
|
||||
ryanpeikou/2,
|
||||
chinitsu/2,
|
||||
kokushi_musou/2,
|
||||
ryuu_iisou/2,
|
||||
dai_san_gen/2]).
|
||||
|
@ -91,8 +97,8 @@ count_unique(L) ->
|
|||
-spec iipeikou(game(), player()) -> boolean().
|
||||
iipeikou(#game{}, #player{hand=#hand{melds=Melds}}) ->
|
||||
Chiis = [M || M = #meld{type=chii} <- Melds],
|
||||
Counts = [C || {_, C} <- count_unique(Chiis)],
|
||||
lists:max(Counts) > 1 andalso lists:max(Counts) < 4.
|
||||
Counts = [C || {_, C} <- count_unique(Chiis), C == 2],
|
||||
length(Counts) == 1.
|
||||
|
||||
%% @doc Returns true for a Chanta hand
|
||||
%% All melds and the pair must include a terminal or honor tile
|
||||
|
@ -164,6 +170,23 @@ san_an_kou(#game{}, #player{hand=#hand{melds=Melds}}) ->
|
|||
lists:member(T, [pon,kan])],
|
||||
length(ClosedPons) =:= 3.
|
||||
|
||||
%% @doc Returns true for a Shou san gen hand
|
||||
shou_san_gen(#game{}, #player{hand=#hand{melds=Melds}}) ->
|
||||
Pons = [M || M = #meld{type=Type, tiles=[#tile{value=Value}|_]} <- Melds,
|
||||
lists:member(Type, [pon, kan]),
|
||||
lists:member(Value, [red, green, white])],
|
||||
Pairs = [M || M = #meld{type=Type, tiles=[#tile{value=Value}|_]} <- Melds,
|
||||
Type == pair,
|
||||
lists:member(Value, [red, green, white])],
|
||||
length(Pons) == 2 andalso length(Pairs) == 1.
|
||||
|
||||
%% @doc Returns true for a Honrouto hand
|
||||
honrouto(#game{}, #player{hand=Hand}) ->
|
||||
IsHonour = fun(T) ->
|
||||
lists:member(T, ?HONOURS ++ ?TERMINALS)
|
||||
end,
|
||||
lists:all(IsHonour, riichi_hand:tiles(Hand)).
|
||||
|
||||
%% @doc Returns true for a 7-pair hand.
|
||||
-spec chiitoitsu(game(), player()) -> boolean().
|
||||
chiitoitsu(#game{}, #player{hand=#hand{tiles=[], melds=Melds}})
|
||||
|
@ -171,6 +194,43 @@ chiitoitsu(#game{}, #player{hand=#hand{tiles=[], melds=Melds}})
|
|||
Pairs = [S || S <- Melds, S#meld.type =:= pair],
|
||||
length(Pairs) =:= 7 andalso sets:size(sets:from_list(Pairs)) =:= 7.
|
||||
|
||||
%% @doc Returns true for a Honitsu hand.
|
||||
honitsu(#game{}, #player{hand=Hand}) ->
|
||||
Tiles = riichi_hand:tiles(Hand),
|
||||
Suits = sets:to_list(sets:from_list([Suit || #tile{suit=Suit} <- Tiles,
|
||||
lists:member(Suit, [pin, sou, man])])),
|
||||
IsHonour = fun(T) ->
|
||||
lists:member(T, ?HONOURS)
|
||||
end,
|
||||
length(Suits) == 1 andalso lists:any(IsHonour, Tiles).
|
||||
|
||||
%% @doc Returns true for a Jun chan hand.
|
||||
jun_chan(#game{}, #player{hand=#hand{melds=Melds}}) ->
|
||||
IsTerminal = fun(T) ->
|
||||
lists:member(T, ?TERMINALS)
|
||||
end,
|
||||
HasTerminal = fun(#meld{tiles=Tiles}) ->
|
||||
lists:any(IsTerminal, Tiles)
|
||||
end,
|
||||
lists:all(HasTerminal, Melds).
|
||||
|
||||
%% @doc Returns true for a Ryanpeikou hand.
|
||||
ryanpeikou(#game{}, #player{hand=#hand{melds=Melds}}) ->
|
||||
Chiis = [M || M = #meld{type=chii} <- Melds],
|
||||
Counts = [C || {_, C} <- count_unique(Chiis), C == 2],
|
||||
length(Counts) == 2.
|
||||
|
||||
%% @doc Returns true for a Chinitsu hand.
|
||||
chinitsu(#game{}, #player{hand=Hand}) ->
|
||||
Tiles = riichi_hand:tiles(Hand),
|
||||
Suits = sets:to_list(sets:from_list([Suit || #tile{suit=Suit} <- Tiles,
|
||||
lists:member(Suit, [pin, sou, man])])),
|
||||
IsHonour = fun(T) ->
|
||||
lists:member(T, ?HONOURS)
|
||||
end,
|
||||
length(Suits) == 1 andalso not lists:any(IsHonour, Tiles).
|
||||
|
||||
|
||||
%% @doc Returns true for a 13 Orphans hand.
|
||||
%% The hand must contain one each of every terminal and honour tile, plus one
|
||||
%% additional tile matching any of the others in the hand.
|
||||
|
|
|
@ -44,6 +44,14 @@ iipeikou_test() ->
|
|||
#meld{type=chii, tiles=[#tile{suit=man, value=V} || V <- [6,7,8]]}]},
|
||||
?assertEqual(true, yaku:iipeikou(#game{}, #player{hand=Hand, drawn={tsumo, #tile{suit=sou, value=6}}})).
|
||||
|
||||
ryanpeikou_not_iipeikou_test() ->
|
||||
Hand = #hand{melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=sou, value=8})},
|
||||
#meld{type=chii, tiles=[#tile{suit=pin, value=V} || V <- [1,2,3]]},
|
||||
#meld{type=chii, tiles=[#tile{suit=sou, value=V} || V <- [4,5,6]]},
|
||||
#meld{type=chii, tiles=[#tile{suit=sou, value=V} || V <- [4,5,6]]},
|
||||
#meld{type=chii, tiles=[#tile{suit=pin, value=V} || V <- [1,2,3]]}]},
|
||||
?assertEqual(false, yaku:iipeikou(#game{}, #player{hand=Hand, drawn={tsumo, #tile{suit=sou, value=6}}})).
|
||||
|
||||
chanta_test() ->
|
||||
Hand = #hand{melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=dragon, value=red})},
|
||||
#meld{type=chii, tiles=[#tile{suit=pin, value=V} || V <- [1,2,3]]},
|
||||
|
@ -100,10 +108,58 @@ san_an_kou_test() ->
|
|||
#meld{type=chii, tiles=[#tile{suit=man, value=V} || V <- [6,7,8]]}]},
|
||||
?assertEqual(true, yaku:san_an_kou(#game{}, #player{hand=Hand, drawn={tsumo, #tile{suit=dragon, value=red}}})).
|
||||
|
||||
shou_san_gen_test() ->
|
||||
Hand = #hand{melds=[#meld{type=chii, tiles=[#tile{suit=sou, value=V} || V <- [2,3,4]]},
|
||||
#meld{type=pon, tiles=lists:duplicate(3, #tile{suit=dragon, value=red})},
|
||||
#meld{type=pon, tiles=lists:duplicate(3, #tile{suit=dragon, value=green})},
|
||||
#meld{type=kan, tiles=lists:duplicate(4, #tile{suit=pin, value=1})},
|
||||
#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=dragon, value=white})}]},
|
||||
?assert(yaku:shou_san_gen(#game{}, #player{hand=Hand})).
|
||||
|
||||
honrouto_test() ->
|
||||
Hand = #hand{melds=[#meld{type=pon, tiles=lists:duplicate(3, #tile{suit=sou, value=1})},
|
||||
#meld{type=pon, tiles=lists:duplicate(3, #tile{suit=sou, value=9})},
|
||||
#meld{type=pon, tiles=lists:duplicate(3, #tile{suit=dragon, value=green})},
|
||||
#meld{type=kan, tiles=lists:duplicate(4, #tile{suit=pin, value=1})},
|
||||
#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=dragon, value=white})}]},
|
||||
?assert(yaku:honrouto(#game{}, #player{hand=Hand})).
|
||||
|
||||
chiitoitsu_test() ->
|
||||
Hand = #hand{melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=pin, value=V})} || V <- lists:seq(1,7)]},
|
||||
?assertEqual(true, yaku:chiitoitsu(#game{}, #player{hand=Hand})).
|
||||
|
||||
honitsu_test() ->
|
||||
Hand = #hand{melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=sou, value=8})},
|
||||
#meld{type=pon, tiles=lists:duplicate(3, #tile{suit=dragon, value=red})},
|
||||
#meld{type=chii, tiles=[#tile{suit=sou, value=V} || V <- [4,5,6]]},
|
||||
#meld{type=chii, tiles=[#tile{suit=sou, value=V} || V <- [4,5,6]]},
|
||||
#meld{type=pon, tiles=lists:duplicate(3, #tile{suit=sou, value=1})}]},
|
||||
?assertEqual(true, yaku:honitsu(#game{}, #player{hand=Hand, drawn={tsumo, #tile{suit=sou, value=1}}})).
|
||||
|
||||
jun_chan_test() ->
|
||||
Hand = #hand{melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=sou, value=9})},
|
||||
#meld{type=chii, tiles=[#tile{suit=pin, value=V} || V <- [1,2,3]]},
|
||||
#meld{type=chii, tiles=[#tile{suit=sou, value=V} || V <- [7,8,9]]},
|
||||
#meld{type=chii, tiles=[#tile{suit=sou, value=V} || V <- [7,8,9]]},
|
||||
#meld{type=chii, tiles=[#tile{suit=pin, value=V} || V <- [1,2,3]]}]},
|
||||
?assertEqual(true, yaku:jun_chan(#game{}, #player{hand=Hand, drawn={tsumo, #tile{suit=sou, value=7}}})).
|
||||
|
||||
ryanpeikou_test() ->
|
||||
Hand = #hand{melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=sou, value=8})},
|
||||
#meld{type=chii, tiles=[#tile{suit=pin, value=V} || V <- [1,2,3]]},
|
||||
#meld{type=chii, tiles=[#tile{suit=sou, value=V} || V <- [4,5,6]]},
|
||||
#meld{type=chii, tiles=[#tile{suit=sou, value=V} || V <- [4,5,6]]},
|
||||
#meld{type=chii, tiles=[#tile{suit=pin, value=V} || V <- [1,2,3]]}]},
|
||||
?assertEqual(true, yaku:ryanpeikou(#game{}, #player{hand=Hand, drawn={tsumo, #tile{suit=sou, value=6}}})).
|
||||
|
||||
chinitsu_test() ->
|
||||
Hand = #hand{melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=sou, value=8})},
|
||||
#meld{type=pon, tiles=lists:duplicate(3, #tile{suit=sou, value=9})},
|
||||
#meld{type=chii, tiles=[#tile{suit=sou, value=V} || V <- [4,5,6]]},
|
||||
#meld{type=chii, tiles=[#tile{suit=sou, value=V} || V <- [4,5,6]]},
|
||||
#meld{type=pon, tiles=lists:duplicate(3, #tile{suit=sou, value=1})}]},
|
||||
?assertEqual(true, yaku:chinitsu(#game{}, #player{hand=Hand, drawn={tsumo, #tile{suit=sou, value=1}}})).
|
||||
|
||||
kokushi_musou_test() ->
|
||||
Hand = #hand{tiles=?TERMINALS ++ ?HONOURS -- [#tile{suit=pin, value=1}],
|
||||
melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=pin, value=1})}]},
|
||||
|
|
Loading…
Reference in a new issue