diff --git a/lib/viral_spiral/room/state/change.ex b/lib/viral_spiral/room/state/change.ex index 4dba351..143c8c1 100644 --- a/lib/viral_spiral/room/state/change.ex +++ b/lib/viral_spiral/room/state/change.ex @@ -7,5 +7,5 @@ defprotocol ViralSpiral.Room.State.Change do - change_description: a Keyword List with parameters defining the change """ @spec apply_change(t(), keyword()) :: t() - def apply_change(score, change_description) + def apply_change(state, change_description) end diff --git a/lib/viral_spiral/room/state/deck.ex b/lib/viral_spiral/room/state/deck.ex new file mode 100644 index 0000000..8bd9428 --- /dev/null +++ b/lib/viral_spiral/room/state/deck.ex @@ -0,0 +1,43 @@ +defmodule ViralSpiral.Room.State.Deck do + alias ViralSpiral.Room.State.Deck + alias ViralSpiral.Room.State.Change + + defstruct available_cards: nil, + dealt_cards: nil + + @type change_opts :: [type: :remove | :shuffle] + @type t :: %__MODULE__{ + available_cards: MapSet.t(), + dealt_cards: MapSet.t() + } + + @doc """ + todo : datastructure of cards, optimized for game operations + """ + def new(cards) do + %Deck{ + available_cards: MapSet.new(cards), + dealt_cards: MapSet.new() + } + end + + defimpl Change do + @doc """ + Handle changes to the deck. + + Possible changes : + - Make card unavailable for drawing. Implemted by change type :remove + - Shuffle card. Implemented by change type :shuffle + """ + @spec apply_change(Deck.t(), Deck.change_opts()) :: Deck.t() + def apply_change(%Deck{} = deck, opts) do + case opts[:type] do + :remove -> + Map.put(deck, :available_cards, MapSet.difference(deck.available_cards, opts[:target])) + + :shuffle -> + Map.put(deck, :availabe_cards, Enum.shuffle(deck)) + end + end + end +end diff --git a/lib/viral_spiral/room/state/round.ex b/lib/viral_spiral/room/state/round.ex index 3ae3b47..771278d 100644 --- a/lib/viral_spiral/room/state/round.ex +++ b/lib/viral_spiral/room/state/round.ex @@ -24,6 +24,8 @@ defmodule ViralSpiral.Room.State.Round do # Doubt should it use game to initialize or players? """ + alias ViralSpiral.Room.State.Change + alias ViralSpiral.Game.Player # alias ViralSpiral.Game.Player @@ -32,6 +34,8 @@ defmodule ViralSpiral.Room.State.Round do current: 0, skip: nil + @type change_opts :: [type: :next] + @type t :: %__MODULE__{ order: list(String.t()), count: integer(), @@ -42,7 +46,8 @@ defmodule ViralSpiral.Room.State.Round do @doc """ todo : this doesn't really need the players, merely a count of players, maybe? """ - def new(player_list) do + @spec new(list(Player.t())) :: ViralSpiral.Room.State.Round.t() + def new(player_list) when is_list(player_list) do order = Enum.shuffle(player_list) |> Enum.map(& &1.id) @@ -108,4 +113,15 @@ defmodule ViralSpiral.Room.State.Round do Map.merge(round, changes) end + + defimpl Change do + alias ViralSpiral.Room.State.Round + + @spec apply_change(Round.t(), Round.change_opts()) :: Round.t() + def apply_change(state, opts) do + case opts[:type] do + :next -> Round.next(state) + end + end + end end diff --git a/lib/viral_spiral/room/state/turn.ex b/lib/viral_spiral/room/state/turn.ex index 3b6b960..146e34f 100644 --- a/lib/viral_spiral/room/state/turn.ex +++ b/lib/viral_spiral/room/state/turn.ex @@ -7,6 +7,7 @@ defmodule ViralSpiral.Room.State.Turn do todo : could the field be actions and not tied to every concrete thing like pass, discard etc. """ + alias ViralSpiral.Room.State.Change alias ViralSpiral.Room.State.Turn alias ViralSpiral.Room.State.Round @@ -61,6 +62,11 @@ defmodule ViralSpiral.Room.State.Turn do ) end - def change(%Turn{} = _turn) do + defimpl Change do + def apply_change(turn, opts) do + case opts[:type] do + :next -> Turn.next(turn, opts[:target]) + end + end end end diff --git a/test/support/fixtures.ex b/test/support/fixtures.ex index 464a637..b17b842 100644 --- a/test/support/fixtures.ex +++ b/test/support/fixtures.ex @@ -51,4 +51,15 @@ defmodule Fixtures do def card_affinity() do Card.new(:affinity) end + + def player_list() do + room_config = %RoomConfig{} + + [ + Player.new(room_config) |> Player.set_name("adhiraj"), + Player.new(room_config) |> Player.set_name("aman"), + Player.new(room_config) |> Player.set_name("krys"), + Player.new(room_config) |> Player.set_name("farah") + ] + end end diff --git a/test/viral_spiral/gameplay_test.exs b/test/viral_spiral/gameplay_test.exs index 7aad115..7a367b4 100644 --- a/test/viral_spiral/gameplay_test.exs +++ b/test/viral_spiral/gameplay_test.exs @@ -18,11 +18,11 @@ defmodule ViralSpiral.GameTest do card = Fixtures.card_affinity() current_player = players[turn.current] - target_player = players[2] + target_player = players[Enum.at(turn.pass_to, 2)] Game.pass_card(game_state, card, current_player, target_player) - IO.inspect(game_state) + # IO.inspect(game_state) # IO.inspect(card) end end diff --git a/test/viral_spiral/room/score/player_text.exs b/test/viral_spiral/room/state/player_text.exs similarity index 100% rename from test/viral_spiral/room/score/player_text.exs rename to test/viral_spiral/room/state/player_text.exs diff --git a/test/viral_spiral/room/score/room_test.exs b/test/viral_spiral/room/state/room_test.exs similarity index 100% rename from test/viral_spiral/room/score/room_test.exs rename to test/viral_spiral/room/state/room_test.exs diff --git a/test/viral_spiral/room/score/round_test.exs b/test/viral_spiral/room/state/round_test.exs similarity index 86% rename from test/viral_spiral/room/score/round_test.exs rename to test/viral_spiral/room/state/round_test.exs index baa4e71..67bdb33 100644 --- a/test/viral_spiral/room/score/round_test.exs +++ b/test/viral_spiral/room/state/round_test.exs @@ -1,4 +1,5 @@ defmodule ViralSpiral.Room.State.RoundTest do + alias ViralSpiral.Room.State.Change alias ViralSpiral.Room.State.Round use ExUnit.Case @@ -72,5 +73,15 @@ defmodule ViralSpiral.Room.State.RoundTest do end describe "changes" do + setup do + player_list = Fixtures.player_list() + round = Round.new(player_list) + %{round: round} + end + + test "move to next round", %{round: round} do + new_round = Change.apply_change(round, type: :next) + assert new_round.current == 1 + end end end diff --git a/test/viral_spiral/room/score/turn_test.exs b/test/viral_spiral/room/state/turn_test.exs similarity index 72% rename from test/viral_spiral/room/score/turn_test.exs rename to test/viral_spiral/room/state/turn_test.exs index 8923ffc..61ae82a 100644 --- a/test/viral_spiral/room/score/turn_test.exs +++ b/test/viral_spiral/room/state/turn_test.exs @@ -1,4 +1,5 @@ defmodule ViralSpiral.Room.State.TurnTest do + alias ViralSpiral.Room.State.Change alias ViralSpiral.Room.State.Turn alias ViralSpiral.Room.State.Round use ExUnit.Case @@ -41,5 +42,19 @@ defmodule ViralSpiral.Room.State.TurnTest do end describe "changes" do + setup do + players = Fixtures.player_list() + round = Round.new(players) + turn = Turn.new(round) + + current_player = Enum.at(round.order, 0) + to_pass_player = Enum.at(round.order, 2) + %{turn: turn, target: to_pass_player} + end + + test "move to next turn", %{turn: turn, target: target} do + new_turn = Change.apply_change(turn, type: :next, target: target) + assert new_turn.current == target + end end end