diff --git a/include/riichi.hrl b/include/riichi.hrl index 40a4ead..add7414 100644 --- a/include/riichi.hrl +++ b/include/riichi.hrl @@ -1,21 +1,21 @@ +-type wind() :: east | south | west | north. +-type dragon() :: green | red | white. + -record(tile, { - suit, - value + suit :: pin | man | sou | wind | dragon, + value :: integer() | wind() | dragon(), + from=draw :: draw | wind() }). +-type tile() :: #tile{}. + +-record(meld, { + type :: pair | chii | pon | kan, + tiles :: [tile()] +}). +-type meld() :: #meld{}. -record(hand, { - tiles=[], - sets=[], - seqs=[] -}). - --record(set, { - count, - tile, - open=true -}). - --record(seq, { - tiles, - open=true + tiles=[] :: [tile()], + melds=[] :: [meld()] }). +-type hand() :: #hand{}. diff --git a/src/riichi_hand.erl b/src/riichi_hand.erl index 5e37c88..445b37d 100644 --- a/src/riichi_hand.erl +++ b/src/riichi_hand.erl @@ -10,21 +10,16 @@ find(Tiles) -> find([], Hand, Possible) -> [Hand|Possible]; -find(Tiles, Hand = #hand{tiles=HT, sets=HS}, Possible) -> - case Tiles of - [T, T, T, T|Rest] -> - find(Rest, Hand#hand{sets=[#set{count=4, tile=T, open=false}|HS]}, Possible); - _ -> [] - end ++ +find(Tiles, Hand = #hand{tiles=HT, melds=HM}, Possible) -> case Tiles of [T, T, T|Rest] -> - find(Rest, Hand#hand{sets=[#set{count=3, tile=T, open=false}|HS]}, Possible); + find(Rest, Hand#hand{melds=[#meld{type=pon, tiles=[T, T, T]}|HM]}, Possible); _ -> [] end ++ case Tiles of [T, T|Rest] -> - find(Rest, Hand#hand{sets=[#set{count=2, tile=T, open=false}|HS]}, Possible); + find(Rest, Hand#hand{melds=[#meld{type=pair, tiles=[T, T]}|HM]}, Possible); _ -> [] end ++ @@ -32,7 +27,7 @@ find(Tiles, Hand = #hand{tiles=HT, sets=HS}, Possible) -> [T1 = #tile{value=V1, suit=S}, T2 = #tile{value=V2, suit=S}, T3 = #tile{value=V3, suit=S}|_] when is_integer(V1) andalso [V1, V2, V3] =:= [V1, V1 + 1, V1 + 2] -> - find(Tiles -- [T1, T2, T3], Hand#hand{sets=[#seq{tiles=[T1, T2, T3], open=false}|HS]}, Possible); + find(Tiles -- [T1, T2, T3], Hand#hand{melds=[#meld{type=chii, tiles=[T1, T2, T3]}|HM]}, Possible); _ -> [] end ++ @@ -41,12 +36,12 @@ find(Tiles, Hand = #hand{tiles=HT, sets=HS}, Possible) -> find(Rest, Hand#hand{tiles=[T|HT]}, Possible) end. -is_complete(#hand{tiles=[], sets=Sets}) -> - Pairs = [S || S <- Sets, S#set.count =:= 2], +is_complete(#hand{tiles=[], melds=Melds}) -> + Pairs = [M || M <- Melds, M#meld.type =:= pair], case length(Pairs) of 1 -> % Four mentsu + 1 pair = 5 sets - length(Sets) =:= 5; + length(Melds) =:= 5; 7 -> % Must be seven *unique* pairs sets:size(sets:from_list(Pairs)) =:= 7; @@ -57,9 +52,9 @@ is_complete(#hand{}=Hand) -> kokushi_musou(Hand). % 13 Orphans -kokushi_musou(#hand{tiles=Tiles, sets=Sets}) when +kokushi_musou(#hand{tiles=Tiles, melds=Melds}) when length(Tiles) =:= 13 - andalso length(Sets) =:= 0 -> + andalso length(Melds) =:= 0 -> not lists:any(fun(#tile{value=V}) -> lists:member(V, lists:seq(2,8)) end, diff --git a/src/yaku.erl b/src/yaku.erl index 79aaeb0..f742c7a 100644 --- a/src/yaku.erl +++ b/src/yaku.erl @@ -5,21 +5,23 @@ -compile([export_all]). -yakuhai(#hand{sets=Sets}) -> - length(lists:filter(fun(T = #tile{}) -> - case T#tile.suit of - wind -> +yakuhai(#hand{melds=Melds}) -> + length(lists:filter(fun(#meld{type=Type, tiles=[T|_]}) -> + case {Type, T} of + {pair, _} -> + false; + {chii, _} -> + false; + {_, #tile{suit=wind}} -> % TODO: Round/Seat Winds false; - dragon -> - true; - _ -> - false + {_, #tile{suit=dragon}} -> + true end end, - Sets)). + Melds)). -tanyao(#hand{sets=Sets}) -> +tanyao(#hand{melds=Melds}) -> not lists:any(fun(T = #tile{}) -> case T#tile.suit of dragon -> @@ -30,32 +32,22 @@ tanyao(#hand{sets=Sets}) -> lists:member(T#tile.value, [1,9]) end end, - Sets). + lists:flatten([Tiles || #meld{tiles=Tiles} <- Melds])). -pinfu(#hand{sets=Sets}) -> +pinfu(#hand{melds=Melds}) -> % TODO: Verify closed, open wait, pair not round/seat wind - lists:all(fun(S) -> - case S of - #seq{} -> - true; - _ -> - false - end - end, - [S || S <- Sets]). + length([M || M = #meld{type=T} <- Melds, T =:= chii]) =:= 4. % 7 Pairs -chiitoitsu(#hand{tiles=[], sets=Sets}) - when length(Sets) =:= 7 -> - Pairs = [S || S <- Sets, S#set.count =:= 2], +chiitoitsu(#hand{tiles=[], melds=Melds}) + when length(Melds) =:= 7 -> + Pairs = [S || S <- Melds, S#meld.type =:= pair], length(Pairs) =:= 7 andalso sets:size(sets:from_list(Pairs)) =:= 7. % 13 Orphans -kokushi_musou(#hand{tiles=Tiles, sets=Sets}) - when length(Tiles) =:= 13 - andalso length(Sets) =:= 0 -> +kokushi_musou(#hand{tiles=Tiles, melds=[#meld{type=pair, tiles=[T,T]}]}) -> not lists:any(fun(#tile{value=V}) -> lists:member(V, lists:seq(2,8)) end, - Tiles) - andalso sets:size(sets:from_list(Tiles)) =:= 13. + [T|Tiles]) + andalso sets:size(sets:from_list([T|Tiles])) =:= 13.