diff --git a/src/riichi.erl b/src/riichi.erl index 26f5b4c..dd58788 100644 --- a/src/riichi.erl +++ b/src/riichi.erl @@ -10,6 +10,7 @@ -export([ is_valid_tile/1, + is_open/1, dora/1, nearest/2, score/3, @@ -32,6 +33,17 @@ is_valid_tile(#tile{suit=Suit, value=Value}) -> is_valid_tile(_) -> false. +-spec is_open(hand() | meld() | tile()) -> boolean(). +is_open(#tile{from=draw}) -> + false; +is_open(#tile{}) -> + true; +is_open(#meld{tiles=Tiles}) -> + lists:any(fun is_open/1, Tiles); +is_open(#hand{tiles=Tiles, melds=Melds}) -> + lists:any(fun is_open/1, Tiles) + orelse lists:any(fun is_open/1, Melds). + -spec dora(tile()) -> tile(). dora(#tile{suit=dragon, value=Value}=Indicator) -> case Value of diff --git a/src/yaku.erl b/src/yaku.erl index 0306827..760edbf 100644 --- a/src/yaku.erl +++ b/src/yaku.erl @@ -19,6 +19,7 @@ san_shoku_douko/2, san_kan_tsu/2, toi_toi/2, + san_an_kou/2, kokushi_musou/2, ryuu_iisou/2, dai_san_gen/2]). @@ -155,6 +156,14 @@ toi_toi(#game{}, #player{hand=#hand{melds=Melds}}) -> lists:member(T, [pon,kan])], length(Pons) =:= 4. +%% @doc Returns true for a San an kou hand +%% Hand must contain three concealed triplets +san_an_kou(#game{}, #player{hand=#hand{melds=Melds}}) -> + ClosedPons = [M || M = #meld{type=T} <- Melds, + not riichi:is_open(M), + lists:member(T, [pon,kan])], + length(ClosedPons) =:= 3. + %% @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 72fe07a..77b7dcc 100644 --- a/test/riichi_yaku_tests.erl +++ b/test/riichi_yaku_tests.erl @@ -92,6 +92,13 @@ toi_toi_test() -> #meld{type=pon, tiles=[#tile{suit=pin, value=V} || V <- [8,8,8]]}]}, ?assertEqual(true, yaku:toi_toi(#game{}, #player{hand=Hand, drawn={tsumo, #tile{suit=dragon, value=red}}})). +san_an_kou_test() -> + Hand = #hand{melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=sou, value=8})}, + #meld{type=kan, tiles=[#tile{suit=sou, value=V} || V <- [1,1,1,1]]}, + #meld{type=kan, tiles=[#tile{suit=man, value=V} || V <- [1,1,1,1]]}, + #meld{type=pon, tiles=[#tile{suit=pin, value=V} || V <- [1,1,1]]}, + #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}}})). chiitoitsu_test() -> Hand = #hand{melds=[#meld{type=pair, tiles=lists:duplicate(2, #tile{suit=pin, value=V})} || V <- lists:seq(1,7)]},