mirror of
https://github.com/correl/riichi.git
synced 2024-11-27 11:09:56 +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,
|
san_kan_tsu/2,
|
||||||
toi_toi/2,
|
toi_toi/2,
|
||||||
san_an_kou/2,
|
san_an_kou/2,
|
||||||
|
shou_san_gen/2,
|
||||||
|
honrouto/2,
|
||||||
|
honitsu/2,
|
||||||
|
jun_chan/2,
|
||||||
|
ryanpeikou/2,
|
||||||
|
chinitsu/2,
|
||||||
kokushi_musou/2,
|
kokushi_musou/2,
|
||||||
ryuu_iisou/2,
|
ryuu_iisou/2,
|
||||||
dai_san_gen/2]).
|
dai_san_gen/2]).
|
||||||
|
@ -91,8 +97,8 @@ count_unique(L) ->
|
||||||
-spec iipeikou(game(), player()) -> boolean().
|
-spec iipeikou(game(), player()) -> boolean().
|
||||||
iipeikou(#game{}, #player{hand=#hand{melds=Melds}}) ->
|
iipeikou(#game{}, #player{hand=#hand{melds=Melds}}) ->
|
||||||
Chiis = [M || M = #meld{type=chii} <- Melds],
|
Chiis = [M || M = #meld{type=chii} <- Melds],
|
||||||
Counts = [C || {_, C} <- count_unique(Chiis)],
|
Counts = [C || {_, C} <- count_unique(Chiis), C == 2],
|
||||||
lists:max(Counts) > 1 andalso lists:max(Counts) < 4.
|
length(Counts) == 1.
|
||||||
|
|
||||||
%% @doc Returns true for a Chanta hand
|
%% @doc Returns true for a Chanta hand
|
||||||
%% All melds and the pair must include a terminal or honor tile
|
%% 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])],
|
lists:member(T, [pon,kan])],
|
||||||
length(ClosedPons) =:= 3.
|
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.
|
%% @doc Returns true for a 7-pair hand.
|
||||||
-spec chiitoitsu(game(), player()) -> boolean().
|
-spec chiitoitsu(game(), player()) -> boolean().
|
||||||
chiitoitsu(#game{}, #player{hand=#hand{tiles=[], melds=Melds}})
|
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],
|
Pairs = [S || S <- Melds, S#meld.type =:= pair],
|
||||||
length(Pairs) =:= 7 andalso sets:size(sets:from_list(Pairs)) =:= 7.
|
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.
|
%% @doc Returns true for a 13 Orphans hand.
|
||||||
%% The hand must contain one each of every terminal and honour tile, plus one
|
%% The hand must contain one each of every terminal and honour tile, plus one
|
||||||
%% additional tile matching any of the others in the hand.
|
%% 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]]}]},
|
#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}}})).
|
?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() ->
|
chanta_test() ->
|
||||||
Hand = #hand{melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=dragon, value=red})},
|
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]]},
|
#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]]}]},
|
#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}}})).
|
?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() ->
|
chiitoitsu_test() ->
|
||||||
Hand = #hand{melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=pin, value=V})} || V <- lists:seq(1,7)]},
|
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})).
|
?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() ->
|
kokushi_musou_test() ->
|
||||||
Hand = #hand{tiles=?TERMINALS ++ ?HONOURS -- [#tile{suit=pin, value=1}],
|
Hand = #hand{tiles=?TERMINALS ++ ?HONOURS -- [#tile{suit=pin, value=1}],
|
||||||
melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=pin, value=1})}]},
|
melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=pin, value=1})}]},
|
||||||
|
|
Loading…
Reference in a new issue