Skip to content

Commit

Permalink
feat: differentiate room_engine out of engine_engine; add playable te…
Browse files Browse the repository at this point in the history
…st for bias cards
  • Loading branch information
dennyabrain committed Sep 16, 2024
1 parent ec23250 commit d653083
Show file tree
Hide file tree
Showing 12 changed files with 279 additions and 40 deletions.
62 changes: 49 additions & 13 deletions lib/viral_spiral/playable.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,39 @@ defprotocol ViralSpiral.Playable do
end

defimpl ViralSpiral.Playable, for: ViralSpiral.Canon.Card.Bias do
def pass(_card, _state, _from, _to) do
IO.inspect("returning changes for Bias card")
require IEx

@doc """
If a player passes a Bias Card the following changes take place:
1. their clout increases by 1
2. their bias against the corresponding community increases by 1
3. every player of that community loses a clout of 1
"""
def pass(card, state, from, to) do
[
{state.turn, [type: :next, target: to]},
{state.players[from], [type: :clout, offset: 1]},
{state.players[from], [type: :bias, target: card.target, offset: 1]}
] ++
(Map.keys(state.players)
|> Enum.filter(&(state.players[&1].identity == card.target))
|> Enum.map(&{state.players[&1], [type: :clout, offset: -1]}))
end

def keep(_card, _state, _from) do
def keep(card, state, from) do
[
{state.round, [type: :next]},
{state.turn, [type: :new, round: state.round]},
{state.players[from], [type: :add_to_hand, card_id: card.id]}
]
end

def discard(_card, _state, _from) do
# @spec discard(%ViralSpiral.Canon.Card.Bias{}, any(), any()) :: nil
def discard(_card, state, _from) do
[
{state.round, [type: :next]},
{state.turn, [type: :new, round: state.round]}
]
end
end

Expand Down Expand Up @@ -67,30 +92,41 @@ defimpl ViralSpiral.Playable, for: ViralSpiral.Canon.Card.Topical do

# Increase passing player's clout
# Update the turn
def pass(_card, %Root{} = state, from, _to) do
def pass(_card, %Root{} = state, from, to) do
[
{state.players[from], [type: :clout, offset: 1]},
{state.turn, [type: :end]}
{state.turn, [type: :next, target: to]}
]
end

def keep(_card, _state, _from) do
{}
def keep(_card, state, from) do
[
{state.round, [type: :next]},
{state.turn, [type: :new, round: state.round]},
{state.players[from], [type: :add_to_hand]}
]
end

def discard(_card, _state, _from) do
# End the turn
def discard(_card, state, _from) do
[
{state.turn, [type: :end]},
{state.turn, [type: :new, round: state.round]}
]
end
end

defimpl ViralSpiral.Playable, for: ViralSpiral.Canon.Card.Conflated do
def pass(_card, _state, _from, _to) do
# IO.inspect("returning changes for Bias card")
def pass(_card, state, _from, _to) do
state
end

def keep(_card, _state, _from) do
def keep(_card, state, _from) do
state
end

def discard(_card, _state, _from) do
def discard(_card, state, _from) do
state
end
end

Expand Down
3 changes: 2 additions & 1 deletion lib/viral_spiral/room/engine_config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ defmodule ViralSpiral.Game.EngineConfig do
alias ViralSpiral.Affinity
alias ViralSpiral.Game.EngineConfig

@type volatility :: :low | :medium | :high
@type t :: %__MODULE__{
affinities: list(Affinity.target()),
communities: list(Bias.target()),
chaos_counter: integer(),
volatility: :low | :medium | :high
volatility: volatility()
}

defstruct affinities: Application.compile_env(:viral_spiral, EngineConfig)[:affinities],
Expand Down
41 changes: 41 additions & 0 deletions lib/viral_spiral/room/room_config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,45 @@ defmodule ViralSpiral.Room.RoomConfig do
@moduledoc """
Room specific configuration for every game.
"""
alias ViralSpiral.Bias
alias ViralSpiral.Affinity
alias ViralSpiral.Room.RoomConfig
alias ViralSpiral.Game.EngineConfig

defstruct affinities: [], communities: [], chaos_counter: 0, volatality: :medium

@type t :: %__MODULE__{
affinities: list(Affinity.target()),
communities: list(Bias.target()),
chaos_counter: integer(),
volatality: EngineConfig.volatility()
}

def new(player_count) do

Check warning on line 19 in lib/viral_spiral/room/room_config.ex

View workflow job for this annotation

GitHub Actions / build-and-deploy

variable "player_count" is unused (if the variable is not meant to be used, prefix it with an underscore)
engine_config = %EngineConfig{}

affinities = engine_config.affinities
total_affinities = length(affinities)

two_affinities =
Stream.repeatedly(fn -> :rand.uniform(total_affinities - 1) end) |> Enum.take(2)

room_affinities = Enum.map(two_affinities, &Enum.at(affinities, &1))

communities = engine_config.communities
total_communities = length(communities)

room_communities =
case total_communities do
x when x <= 3 -> Enum.shuffle(communities) |> Enum.take(2)
_ -> communities
end

%RoomConfig{
affinities: room_affinities,
communities: room_communities,
chaos_counter: engine_config.chaos_counter,
volatality: engine_config.volatility
}
end
end
14 changes: 14 additions & 0 deletions lib/viral_spiral/room/state/change.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,17 @@ defprotocol ViralSpiral.Room.State.Change do
@spec apply_change(t(), State.t(), keyword()) :: t()
def apply_change(state, global_state, change_description)
end

defmodule ViralSpiral.Room.State.ChangeOptions do
defstruct type: nil,
target: nil,
id: nil,
extra: nil

@type t :: %__MODULE__{
type: atom(),
target: atom(),
id: String.t(),
extra: any()
}
end
55 changes: 51 additions & 4 deletions lib/viral_spiral/room/state/player.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ defmodule ViralSpiral.Room.State.Player do
clout: 0
}
"""
alias ViralSpiral.Room
alias ViralSpiral.Room.RoomConfig
alias ViralSpiral.Room.State.Player.ActiveCardDoesNotExist
alias ViralSpiral.Room.State.Player.DuplicateActiveCardException
alias ViralSpiral.Room.State.Player
Expand Down Expand Up @@ -37,8 +39,8 @@ defmodule ViralSpiral.Room.State.Player do
active_cards: list(String.t())
}

@spec new(EngineConfig.t()) :: t()
def new(%EngineConfig{} = room_config) do
@spec new(RoomConfig.t()) :: t()
def new(%RoomConfig{} = room_config) do
identity = Enum.shuffle(room_config.communities) |> Enum.at(0)

bias_list = Enum.filter(room_config.communities, &(&1 != identity))
Expand Down Expand Up @@ -72,7 +74,7 @@ defmodule ViralSpiral.Room.State.Player do
end

def add_to_hand(%Player{} = player, card_id) do
Map.put(player, :hand, player.hand ++ card_id)
Map.put(player, :hand, player.hand ++ [card_id])
end

@spec add_active_card(Player.t(), String.t()) :: Player.t()
Expand All @@ -91,6 +93,8 @@ defmodule ViralSpiral.Room.State.Player do
end
end

def clout(%Player{} = player), do: player.clout

@doc """
Change a Player's Score.
Expand Down Expand Up @@ -152,7 +156,7 @@ defimpl ViralSpiral.Room.State.Change, for: ViralSpiral.Room.State.Player do
:clout -> Player.change(player, :clout, change_desc[:offset])
:affinity -> Player.change(player, :affinity, change_desc[:target], change_desc[:offset])
:bias -> Player.change(player, :bias, change_desc[:target], change_desc[:offset])
:add_to_hand -> player
:add_to_hand -> Player.add_to_hand(player, change_desc[:card_id])
:remove_from_hand -> player
:add_active_card -> Player.add_active_card(player, change_desc[:card_id])
:remove_active_card -> Player.remove_active_card(player, change_desc[:card_id])
Expand All @@ -167,3 +171,46 @@ end
defmodule ViralSpiral.Room.State.Player.ActiveCardDoesNotExist do
defexception message: "This card is not an active card for this player "
end

defmodule ViralSpiral.Room.State.Players do
@moduledoc """
Functions for handling a collection of `ViralSpiral.Room.State.Player`
"""
alias ViralSpiral.Room.State.Player
import ViralSpiral.Game.EngineConfig.Guards

@doc """
Return all players of an identity
"""
def of_identity(players, identity) when is_community(identity) and is_map(players) do
Map.keys(players)
|> Enum.filter(&(players[&1].identity == identity))
|> to_full_map(players)
end

@doc """
Return all players not of an identity
"""
def not_of_identity(players, identity) when is_community(identity) and is_map(players) do
Map.keys(players)
|> Enum.filter(&(players[&1].identity != identity))
end

@doc """
Return all players other than me
"""
# @spec(map(String.t(), Player.t()), String.t() :: list(Player.t()))
def others(players, me) when is_map(players) and is_bitstring(me) do
Map.keys(players)
|> Enum.filter(&(&1 != me))
|> Enum.reduce(%{}, &Map.put(&2, &1, players[&1]))
end

def to_map(players) when is_list(players) do
Enum.reduce(players, %{}, &Map.put(&2, &1.id, &1))
end

def to_full_map(ids, players) when is_list(ids) do
Enum.reduce(ids, %{}, &Map.put(&2, &1, players[&1]))
end
end
6 changes: 3 additions & 3 deletions lib/viral_spiral/room/state/root.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@ defmodule ViralSpiral.Room.State.Root do
When a round begins, we also start a Turn. Within each Round there's a turn that includes everyone except the person who started the turn.
"""

alias ViralSpiral.Room.RoomConfig
alias ViralSpiral.Room.State.Turn
alias ViralSpiral.Canon.Deck
alias ViralSpiral.Room.State.Round
alias ViralSpiral.Room.State.Room
alias ViralSpiral.Room.State.Player
alias ViralSpiral.Game.EngineConfig
alias ViralSpiral.Room.State.Root
alias ViralSpiral.Room.State.Change

defstruct engine_config: nil,
defstruct room_config: nil,
room: nil,
players: [],
round: nil,
turn: nil,
deck: nil

@type t :: %__MODULE__{
engine_config: EngineConfig.t(),
room_config: RoomConfig.t(),
room: Room.t(),
players: list(Player.t()),
round: Round.t()
Expand Down
7 changes: 2 additions & 5 deletions lib/viral_spiral/room/state/round.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,8 @@ defmodule ViralSpiral.Room.State.Round do
Round.next(round)
## Fields
- `order` - Player IDs in the order in which they draw a card.
# Doubt
should it use game to initialize or players?
- order: Player IDs in the order in which they draw a card.
- current: index of the player whose round it is
"""
alias ViralSpiral.Room.State.Player
alias ViralSpiral.Room.State.Change
Expand Down
11 changes: 11 additions & 0 deletions test/support/card_fixtures.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
defmodule CardFixtures do
alias ViralSpiral.Canon.Card.Affinity
alias ViralSpiral.Canon.Card.Bias
import ViralSpiral.Game.EngineConfig.Guards

@doc """
attrs is a map with keys suitable for`ViralSpiral.Canon.Card.Affinity`
Expand All @@ -14,4 +16,13 @@ defmodule CardFixtures do
def affinity_card_true_pro_cat(attrs \\ %{}) do
struct(%Affinity{target: :cat, veracity: true, polarity: :positive}, attrs)
end

def bias_card(target, veracity, attrs \\ %{})
when is_boolean(veracity)
when is_community(target) do
struct(
%Bias{id: "card_BNEQQW", target: target, veracity: veracity},
attrs
)
end
end
24 changes: 12 additions & 12 deletions test/support/fixtures.ex
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
defmodule Fixtures do
alias ViralSpiral.Room.RoomConfig
alias ViralSpiral.Room.State.Player
alias ViralSpiral.Deck.Card
alias ViralSpiral.Room.State.Turn
alias ViralSpiral.Room.State.Round
alias ViralSpiral.Room.State.Room
alias ViralSpiral.Game.EngineConfig
# alias ViralSpiral.Game.Score.Room, as: RoomScore

alias ViralSpiral.Room.State.Root

def initialized_game() do
engine_config = %EngineConfig{}
room_config = RoomConfig.new(4)

player_list = [
Player.new(engine_config) |> Player.set_name("adhiraj"),
Player.new(engine_config) |> Player.set_name("aman"),
Player.new(engine_config) |> Player.set_name("krys"),
Player.new(engine_config) |> Player.set_name("farah")
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")
]

players = Enum.reduce(player_list, %{}, fn player, acc -> Map.put(acc, player.id, player) end)
Expand All @@ -25,7 +25,7 @@ defmodule Fixtures do
turn = Turn.new(round)

%Root{
engine_config: engine_config,
room_config: room_config,
room: Room.new(),
players: players,
round: round,
Expand All @@ -34,13 +34,13 @@ defmodule Fixtures do
end

def players() do
engine_config = %EngineConfig{}
room_config = %RoomConfig{}

player_list = [
Player.new(engine_config) |> Player.set_name("adhiraj"),
Player.new(engine_config) |> Player.set_name("aman"),
Player.new(engine_config) |> Player.set_name("krys"),
Player.new(engine_config) |> Player.set_name("farah")
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")
]

Enum.reduce(player_list, %{}, fn player, acc -> Map.put(acc, player.id, player) end)
Expand Down
Loading

0 comments on commit d653083

Please sign in to comment.