Working and understanding GenServer


I am new to GenServer and I am having a hard time understanding it. I am trying to create a war card game. I am using GenServer to set up a server, client’s API’s and server callbacks. Functions I want to create are:

  • starting a game
  • adding a deck
  • shuffling a deck
  • placing a bet
  • drawing players card
  • drawing computers card

Up until now I have:

defmodule WarGame.Boundary.GameManager do
  use GenServer
  alias WarGame.Core.Game
  alias WarGame.Core.Deck

  # Client API
  def start_link(options \\ []) do
    GenServer.start_link(__MODULE__, %{}, options)

  def start_game(manager \\ __MODULE__, game_fields) do, {:start_game, game_fields})

  def add_deck(manager \\__MODULE__) do, {:add_deck})

  # Server Callbackszz

  def init(war_game) do
    {:ok, war_game}

  def handle_call({:add_deck}, _from. war_game) do
    deck = Deck.new_deck()
    game = %Game{}
    new_war_game = Map.put(war_game, game.deck, deck)

    {:reply, :ok, new_war_game}

  def handle_call({:start_game, game_fields}, _from, war_game) do
    game =
    new_war_game = Map.put(war_game, game.user_cards, game)

    {:reply, :ok, new_war_game}



I managed to start a server and start a game. However, I don’t know how to add fields etc, so my add_deck call doesn’t work.
This is my WarGame.Core.Deck

defmodule WarGame.Core.Deck do

  defmodule Card do
    defstruct value: [],
              suit: []

  def new_deck do
    for  suit <- suits(), value <- values() do
      %Card{value: value, suit: suit}

  def shuffle(new_deck) do
    |> Enum.shuffle()

  def deal_a_card(cards) do
    [card | new_deck] = shuffle(cards)
    [{to_tuple(card), new_deck}]

  defp to_tuple(
    %WarGame.Core.Deck.Card{value: value, suit: suit}
    ), do: {value, suit}

  defp values(), do: Enum.to_list(2..14)
  defp suits(), do: [:hearts, :diamonds, :spades, :clubs]


My WarGame.Core.Game

defmodule WarGame.Core.Game do

  defstruct user_cards: [],
            croupier_cards: [],
            user_bets: [],
            deck: %{},
            used: []

  def new(fields) do
    struct!(__MODULE__, fields)


I will be thankful for explanation how to update, change and show fields using GenServer in simple words. I did read documentations but as you can see it didn’t help. I did try Map.update but I am not getting it :frowning:

Best wishes to all!

Your Map.put doesn’t look right. Map.put takes a map, then the key to insert, then the value to insert.

In your handle_call functions, you’re creating an new Game struct, whose default deck is an empty map and then using that empty map as the key to insert into the state. Such that it looks like new_war_game = Map.put(war_game, %{}, deck) I presume you want to add the new deck to the game, which is Map.put(war_game, :deck, Deck.new_deck()) or %Game{ war_game | deck: Deck.new_deck()}.

Something like this?

def handle_call({:add_deck}, _from. war_game) do
    {:reply, :ok, %Game{ war_game | deck: Deck.new_deck()}

  def handle_call({:start_game, game_fields}, _from, war_game) do
    game =
    {:reply, :ok, game}
1 Like

Thanks for reply!

Yes, that’s what I was looking for! I will try to implement your suggestions to further functions.

1 Like


I tried to follow your explanation with :shuffle_deck but I guess I am not getting it.

What am I doing wrong?

  def shuffle_deck(manager \\ __MODULE__, deck_field) do, {:shuffle_deck, deck_field})

  def handle_call({:shuffle_deck, deck_field}, _from, war_game) do
    {:reply, :ok, %Game{ war_game | deck: Deck.shuffle(deck_field)}}

What is deck_field supposed to be? Deck.shuffle takes a deck. You already have a deck in your state, so shuffle it. You could put Deck.shuffle(war_game.deck) in what you have or do a Map.update(war_game, :deck, &Deck.shuffle/1) to get the new state.

1 Like

So once I initialized my deck I don’t need to bother doing it again? I didn’t get that.
deck_field was supposed to be a deck.