Download:
child 1:f44d2a7c91f4
0:58a061003687
Anton Shestakov <engored@ya.ru>, Sun, 23 Feb 2014 00:04:28 +0900
Working thing.

1 файлов изменено, 108 вставок(+), 0 удалений(-) [+]
rps.erl file | annotate | diff | comparison | revisions
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rps.erl Sun Feb 23 00:04:28 2014 +0900
@@ -0,0 +1,108 @@
+-module(rps).
+-export([lobby/0, room/1, beats/1, winner/1, go/0, fool/1]).
+
+-define(RULES, [rock, paper, scissors]).
+
+beats(C) ->
+ beats(C, ?RULES).
+
+beats(C, [C|Tail]) ->
+ lists:last(Tail);
+
+beats(C, [B,C|_]) ->
+ B;
+
+beats(C, [_|T]) ->
+ beats(C, T).
+
+% winner for 3 players is:
+% rock, rock, rock -> undefined
+% rock, paper, scissors -> undefined
+% rock, paper, paper -> undefined
+% rock, rock, paper -> {paper, Who}
+
+winner(Choices) when length(Choices) > 1 ->
+ CSet = sets:from_list([C || {C, _} <- Choices]),
+ RSet = sets:from_list(?RULES),
+ Absents = sets:subtract(RSet, CSet),
+ case sets:size(Absents) of
+ 1 ->
+ Absent = hd(sets:to_list(Absents)),
+ Unbeaten = beats(Absent),
+ Winners = [{C, Who} || {C, Who} <- Choices, C =:= Unbeaten],
+ case length(Winners) of
+ 1 -> hd(Winners);
+ _ -> undefined
+ end;
+ _ -> undefined
+ end.
+
+go() ->
+ Lobby = spawn(rps, lobby, []),
+ [spawn(rps, fool, [Lobby]) || _ <- lists:seq(1, 3)].
+
+lobby() ->
+ lobby([]).
+
+lobby(Players) when length(Players) =:= 3 ->
+ Room = spawn(rps, room, [Players]),
+ lists:foreach(fun(Player) -> Player ! {room, Room} end, Players),
+ lobby([]);
+
+lobby(Players) ->
+ receive
+ {join, Who} ->
+ lobby([Who|Players])
+ end.
+
+room(Players) ->
+ lists:foreach(fun(Player) -> Player ! start end, Players),
+ room(Players, []).
+
+room(Players, Choices) when length(Players) =:= length(Choices) ->
+ Best = winner(Choices),
+ Msg = if
+ Best =:= undefined ->
+ io:format("draw: ~w.~n", [Choices]),
+ draw;
+ true ->
+ io:format("the winner is ~w.~n", [Best]),
+ {winner, Best}
+ end,
+ lists:foreach(fun(Player) -> Player ! Msg end, Players),
+ room(Players);
+
+room(Players, Choices) ->
+ receive
+ {Object, Who} ->
+ ObjectIsOk = lists:any(fun(X) -> X =:= Object end, ?RULES),
+ ChoiceMade = lists:any(fun({_, Player}) -> Player =:= Who end, Choices),
+ case ObjectIsOk andalso not ChoiceMade of
+ true ->
+ room(Players, [{Object, Who}|Choices]);
+ false ->
+ io:format("~w picks ~w, not allowed.~n", [Who, Object]),
+ room(Players, Choices)
+ end
+ end.
+
+fool(Lobby) ->
+ Lobby ! {join, self()},
+ fool(Lobby, undefined).
+
+fool(Lobby, undefined) ->
+ receive
+ {room, Room} ->
+ random:seed(now()),
+ fool(Lobby, Room)
+ end;
+
+fool(Lobby, Room) ->
+ receive
+ start ->
+ Choice = lists:nth(random:uniform(length(?RULES)), ?RULES),
+ Room ! {Choice, self()},
+ fool(Lobby, Room);
+ {winner, _} ->
+ fool(Lobby, Room)
+ end.