2
votes

i'm trying to model a game of poker.

My game state representation is in a map, for this question i'm only interested in the players.

{:players {:1 {:money 200} :2 {money 400}}}

Every function takes in a game state and some other parameters and return a new game state, for example:

(defn update-player-money
  "Returns new game state where player has added amount to his money"
  [game-state player amount]
  (assoc-in game-state [:players player :money]
            (+ (-> game-state :players player :money)
               amount)))

Now i want a function that removes a certain amount of money from each player while passing down the new game state. To make it clear, something that for two players would do:

(update-player-money (update-player-money game-state :1 (- 20)) :2 (-20))

This is what i came up with:

(defn phase-1-blind
  "Removes blind from all players."
  [game-state blind-amount]
  (letfn [(blind-helper [game-state player-list amount]
            (if (seq player-list)
              (blind-helper (update-player-money game-state
                                                 (first player-list)
                                                 (- amount))
                            (rest player-list)
                            amount)
              game-state))]
  (blind-helper game-state (keys (:players game-state)) blind-amount)))

This works but i was wondering if there was a more idiomatic or concise way to achieve the same effect.

1
have you checked update-in ?Jochen Bedersdorfer
update-in would certainly improve the update-player-money function. Would there be a better alternative than writing the recursion by hand in the second function?Marco Grassi
Another food for thoughts: if you separate updating the money of a player and updating the money of a player inside the gamestate, you can reuse the previous function.cfrick
:1 isn't idiomatic. Just use 1souenzzo

1 Answers

2
votes

If you want to implement phase-1-blind using update-player-money, reduce is useful here:

(defn update-player-money
  "Returns new game state where player has added amount to his money"
  [game player-id amt]
  (update-in game [:players player-id :money] (fnil + 0) amt))

(defn phase-1-blind
  "Removes blind from all players."
  [game blind]
  (reduce #(update-player-money % %2 blind)
          game
          (keys (:players game))))

In update-player-money, fnil makes sure things don't break, even if a player doesn't have the :money key in it.