Skip to content

Instantly share code, notes, and snippets.

@qw3r
Last active May 24, 2018 00:42
Show Gist options
  • Save qw3r/a50269177a728fa3fb78867a6b56d981 to your computer and use it in GitHub Desktop.
Save qw3r/a50269177a728fa3fb78867a6b56d981 to your computer and use it in GitHub Desktop.
War Erlang ch008, Processes Etude
-module(cards).
-export([make_deck/0, shuffle/1]).
make_deck() ->
[{Rank, Suit} || Rank <- ["A", 2, 3, 4, 5, 6, 7, 8, 9, 10, "J", "Q", "K"],
Suit <- ["Clubs", "Diamonds", "Hearts", "Spades"]].
shuffle(List) -> shuffle(List, []).
shuffle([], Acc) -> Acc;
shuffle(List, Acc) ->
{Leading, [H | T]} = lists:split(rand:uniform(length(List)) - 1, List),
shuffle(Leading ++ T, [H | Acc]).
-module(war).
-import(cards, [make_deck/0, shuffle/1]).
-export([start/0, player/1]).
start() ->
{DeckForPlayer1, DeckForPlayer2} = lists:split(26, shuffle(make_deck())),
Players = [
spawn(?MODULE, player, [DeckForPlayer1]),
spawn(?MODULE, player, [DeckForPlayer2])
],
battle(Players).
battle(Players) ->
lists:foreach(fun(Player) -> Player ! {self(), give, 1} end, Players),
wait(Players, [], []).
battle(Players, Pile) ->
lists:foreach(fun(Player) -> Player ! {self(), give, 3} end, Players),
wait(Players, [], Pile).
wait(Players, Hands, Pile) ->
receive
{Sender, card, []} = Message ->
log(Message),
lists:foreach(fun(Player) -> Player ! {self(), bye} end, Players),
#{winner => hd(Players -- [Sender]), looser => Sender};
{Sender, card, Cards} = Message when length(Hands) =:= 0 ->
log(Message),
wait(Players, Hands ++ [{Sender, Cards}], Pile);
{Sender, card, Cards} = Message when length(Hands) =:= 1 ->
log(Message),
check(Players, Hands ++ [{Sender, Cards}], Pile)
end.
check(Players, [{Player1, Cards1}, {Player2, Cards2}], Pile) ->
ValueOfHand1 = get_card_value(lists:last(Cards1)),
ValueOfHand2 = get_card_value(lists:last(Cards2)),
if
ValueOfHand1 > ValueOfHand2 ->
Player1 ! {self(), won, Pile ++ Cards1 ++ Cards2},
battle(Players);
ValueOfHand1 < ValueOfHand2 ->
Player2 ! {self(), won, Pile ++ Cards1 ++ Cards2},
battle(Players);
ValueOfHand1 =:= ValueOfHand2 ->
battle(Players, Pile ++ Cards1 ++ Cards2)
end.
get_card_value({Rank, _Suit}) when is_integer(Rank) -> Rank;
get_card_value({"J", _Suit}) -> 11;
get_card_value({"Q", _Suit}) -> 12;
get_card_value({"K", _Suit}) -> 13;
get_card_value({"A", _Suit}) -> 14.
player(Cards) ->
receive
{Sender, give, N} = Message ->
log(Message),
if
length(Cards) >= N ->
{CardToGive, CardsToKeep} = lists:split(N, Cards);
true ->
{CardToGive, CardsToKeep} = {Cards, []}
end,
Sender ! {self(), card, CardToGive},
player(CardsToKeep);
{Sender, won, CardsIWon} = Message ->
log(Message),
player(Cards ++ CardsIWon);
{Sender, bye} = Message ->
log(Message)
end.
log(Message) ->
io:format("[~p - ~p] ~p~n", [erlang:system_time(), self(), Message]),
ok.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment