diff --git a/src/yaku.erl b/src/yaku.erl index d7fd17a..aefd827 100644 --- a/src/yaku.erl +++ b/src/yaku.erl @@ -9,12 +9,13 @@ -include("../include/riichi.hrl"). -export([yakuhai/2, - tanyao/2, - pinfu/2, - chiitoitsu/2, - kokushi_musou/2, - ryuu_iisou/2, - dai_san_gen/2]). + tanyao/2, + pinfu/2, + iipeikou/2, + chiitoitsu/2, + kokushi_musou/2, + ryuu_iisou/2, + dai_san_gen/2]). %% @doc Counts the pons/kans of value tiles in a player's hand. %% Value tiles include all of the dragons, plus the round wind and the player's seat wind. @@ -67,6 +68,25 @@ pinfu(#game{round=Round}, #player{seat=Seat, hand=Hand=#hand{melds=Melds}, drawn andalso HeadTile#tile.suit =/= dragon, Closed and OpenWait and Chiis and NonValuePair. +%% @doc Counts unique elements in a list +-spec count_unique(list()) -> list({term(), integer()}). +count_unique(L) -> + Unique = sets:to_list(sets:from_list(L)), + [{I, length(lists:filter(fun (X) -> + X == I + end, + L))} + || I <- Unique]. + +%% @doc Returns true for a hand containing two identical straights in the same suit +%% Will NOT return true if there are more than two, as this yaku and ryanpeikou +%% are mutually exclusive. +-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. + %% @doc Returns true for a 7-pair hand. -spec chiitoitsu(game(), player()) -> boolean(). chiitoitsu(#game{}, #player{hand=#hand{tiles=[], melds=Melds}}) diff --git a/test/riichi_yaku_tests.erl b/test/riichi_yaku_tests.erl index 78ed9b1..d7d6cd0 100644 --- a/test/riichi_yaku_tests.erl +++ b/test/riichi_yaku_tests.erl @@ -36,6 +36,14 @@ pinfu_test() -> #meld{type=chii, tiles=[#tile{suit=man, value=V} || V <- [6,7,8]]}]}, ?assertEqual(true, yaku:pinfu(#game{}, #player{hand=Hand, drawn={tsumo, #tile{suit=sou, value=6}}})). +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=man, value=V} || V <- [6,7,8]]}]}, + ?assertEqual(true, yaku:iipeikou(#game{}, #player{hand=Hand, drawn={tsumo, #tile{suit=sou, value=6}}})). + 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})).