2012-05-04 12:18:08 +00:00
|
|
|
-module(riichi).
|
|
|
|
|
|
|
|
-include("riichi.hrl").
|
|
|
|
|
|
|
|
-export([
|
|
|
|
is_valid_tile/1,
|
|
|
|
dora/1,
|
|
|
|
nearest/2,
|
2012-05-08 04:46:15 +00:00
|
|
|
score/3,
|
|
|
|
score_hand/1,
|
|
|
|
score_hand/2,
|
|
|
|
score_hand/3
|
2012-05-04 12:18:08 +00:00
|
|
|
]).
|
|
|
|
|
|
|
|
is_valid_tile(#tile{suit=dragon, value=Value}) ->
|
|
|
|
lists:member(Value, [white, green, red]);
|
|
|
|
is_valid_tile(#tile{suit=wind, value=Value}) ->
|
|
|
|
lists:member(Value, [east, south, west, north]);
|
|
|
|
is_valid_tile(#tile{suit=Suit, value=Value}) ->
|
|
|
|
ValidSuit = lists:member(Suit, [pin, sou, man]),
|
|
|
|
ValidValue = is_integer(Value) and (Value > 0) and (Value < 10),
|
|
|
|
ValidSuit and ValidValue;
|
|
|
|
is_valid_tile(_) ->
|
|
|
|
false.
|
|
|
|
|
|
|
|
dora(#tile{suit=dragon, value=Value}=Indicator) ->
|
|
|
|
case Value of
|
|
|
|
white -> Indicator#tile{value=green};
|
|
|
|
green -> Indicator#tile{value=red};
|
|
|
|
red -> Indicator#tile{value=white}
|
|
|
|
end;
|
|
|
|
dora(#tile{suit=wind, value=Value}=Indicator) ->
|
|
|
|
case Value of
|
|
|
|
east -> Indicator#tile{value=south};
|
|
|
|
south -> Indicator#tile{value=west};
|
|
|
|
west -> Indicator#tile{value=north};
|
|
|
|
north -> Indicator#tile{value=east}
|
|
|
|
end;
|
|
|
|
dora(#tile{value=Value}=Indicator) ->
|
|
|
|
case is_valid_tile(Indicator) of
|
|
|
|
false ->
|
|
|
|
throw({error, invalid_tile});
|
|
|
|
_ ->
|
|
|
|
if
|
|
|
|
Value == 9 -> Indicator#tile{value=1};
|
|
|
|
true -> Indicator#tile{value=Value + 1}
|
|
|
|
end
|
|
|
|
end.
|
|
|
|
|
|
|
|
nearest(Num, To) when Num rem To == 0 ->
|
|
|
|
Num;
|
|
|
|
nearest(Num, To) ->
|
|
|
|
Num - (Num rem To) + To.
|
|
|
|
|
|
|
|
|
2012-05-04 17:49:13 +00:00
|
|
|
score(_Fu, Han, Limit) when (Han >= 5) and (Limit == true) ->
|
2012-05-04 12:18:08 +00:00
|
|
|
if
|
2012-05-04 17:49:13 +00:00
|
|
|
Han < 6 ->
|
2012-05-04 12:18:08 +00:00
|
|
|
2000;
|
2012-05-04 17:49:13 +00:00
|
|
|
Han < 8 ->
|
2012-05-04 12:18:08 +00:00
|
|
|
3000;
|
2012-05-04 17:49:13 +00:00
|
|
|
Han < 11 ->
|
2012-05-04 12:18:08 +00:00
|
|
|
4000;
|
2012-05-08 04:45:41 +00:00
|
|
|
Han < 13 ->
|
2012-05-04 12:18:08 +00:00
|
|
|
6000;
|
|
|
|
true ->
|
|
|
|
8000
|
|
|
|
end;
|
2012-05-04 17:49:13 +00:00
|
|
|
score(Fu, Han, Limit) ->
|
|
|
|
Score = nearest(Fu * round(math:pow(2, 2 + Han)), 100),
|
2012-05-04 12:18:08 +00:00
|
|
|
if
|
|
|
|
Limit and (Score > 2000) ->
|
|
|
|
2000;
|
|
|
|
true ->
|
|
|
|
Score
|
|
|
|
end.
|
2012-05-08 04:46:15 +00:00
|
|
|
|
|
|
|
score_hand(#hand{}=H) ->
|
|
|
|
score_hand(H, 20).
|
|
|
|
|
|
|
|
score_hand(#hand{}=H, Fu) ->
|
|
|
|
score_hand(H, Fu, true).
|
|
|
|
|
|
|
|
score_hand(#hand{tiles=T, sets=_S}=_H, BaseFu, Limit) ->
|
|
|
|
Fu = [
|
|
|
|
BaseFu
|
|
|
|
],
|
|
|
|
Han = [
|
|
|
|
_DaiSanGen = case sets:is_subset(sets:from_list([{3, #tile{suit=dragon, value=red}}, {3, #tile{suit=dragon, value=white}}, {3, #tile{suit=dragon, value=green}}]), sets:from_list(find_sets(T))) of
|
|
|
|
true -> 13;
|
|
|
|
_ -> 0
|
2012-05-08 05:06:00 +00:00
|
|
|
end,
|
|
|
|
_Kokushi_Musou = case (lists:flatten([lists:duplicate(12, 1), [2]]) == lists:sort([C || {C, _T} <- find_sets(T)])) and (not lists:any(fun(#tile{value=V}) -> lists:member(V, lists:seq(2,8)) end, T)) of
|
|
|
|
true -> 13;
|
|
|
|
_ -> 0
|
2012-05-08 04:46:15 +00:00
|
|
|
end
|
|
|
|
],
|
|
|
|
score(lists:sum(Fu), lists:sum(Han), Limit).
|
|
|
|
|
|
|
|
find_sets(Tiles) ->
|
|
|
|
Unique = sets:to_list(sets:from_list(Tiles)),
|
|
|
|
[{length(lists:filter(fun(X) -> X == T end, Tiles)), T}
|
|
|
|
|| T <- Unique].
|