~subsetpark/whist

c761d0322542e1505b23b587b93f758c8ef4afc5 — Zach Smith 6 months ago 9fa71c1
Output play.janet from .lit file
2 files changed, 82 insertions(+), 45 deletions(-)

M game/play.janet
M whist.lit
M game/play.janet => game/play.janet +60 -45
@@ 1,9 1,9 @@
## game/play.janet
(import cards)
(import players)
(import events)

(def score-threshold 7)
 
# Play utility logic
## New Suit
(defn- new-suit
  ```
  Determine the led suit in a given trick.


@@ 15,7 15,7 @@
    - Otherwise, the led suit is the trump suit.
  ```
  [current-suit bid card-played]
  # We need to explicitly set the current suit to null. This
  # We need to explicitly set the current suit to `"undefined"`. This
  # allows us to check for the edge case where the suit has
  # not been set, even after a card (or two) has been played
  # - if the first card is a Joker, and it's no trumps.


@@ 26,35 26,7 @@
      [trumps "joker"] trumps
      [_ led-suit] led-suit)))

(defn- with-player [card player] (merge-into @{:player player} card))

(defn- add-to-stack [stack card] (tuple ;stack card))

(defn- continue-trick
  ```
  Handle the first, second or third player playing to a trick.

  Set the led suit if necessary, update the stack and prompt the next player in sequence.
  ```
  [players
   {:meta {:bid current-bid :suit current-suit} :info info}
   current-trick
   just-played]
  (let [new-suit (new-suit current-suit current-bid just-played)
        id-to-prompt (players/next-player (just-played :player) players)
        hand-to-prompt (-> |(= ($0 :id) id-to-prompt)
                           (find players)
                           (in :hand))
        play-prompt (->> (cards/of-suit-or-off new-suit current-bid hand-to-prompt)
                         (events/prompt-play id-to-prompt))]

    [{:phase "play"
      :info info
      :meta {:bid current-bid :suit new-suit}
      :stacks {:trick current-trick}}
     [(events/add-decoration (just-played :player) "play_action" (string "played " (cards/to-text just-played)))
      play-prompt]]))

## Total Tricks
(defn- bidding-team
  [players bid]
  ((find |(= ($0 :id) (bid :player)) players) :team))


@@ 71,13 43,7 @@
	 (map |(info $0))
	 (sum))))

(defn- made-bid?
  ```
  A team has made a bid if their combined tricks is greater than or equal to their bid + 6.
  ```
  [total-tricks bid]
  (>= total-tricks (+ 6 (bid :count)))) 

## Bid Values
(defn- adjustment-for-bid
  ```
  A contract's value is its numerical value, or double its value if it's notrumps.


@@ 86,14 52,56 @@
  (case (bid :suit)
    "notrumps" |(* $0 2)
    |$0))
 

(defn- tricks-value
  [total-tricks]
  (- total-tricks 6))

## Made Bid?
(def- score-threshold 7)

(defn- won? [val] (>= val score-threshold))
(defn- lost? [val] (<= val (- score-threshold)))

(defn- made-bid?
  ```
  A team has made a bid if their combined tricks is greater than or equal to their bid + 6.
  ```
  [total-tricks bid]
  (>= total-tricks (+ 6 (bid :count)))) 

# Possible branches of a play state transition
## Continue the Trick
(defn- with-player [card player] (merge-into @{:player player} card))

(defn- continue-trick
  ```
  Handle the first, second or third player playing to a trick.

  Set the led suit if necessary, update the stack and prompt the next player in sequence.
  ```
  [players
   {:meta {:bid current-bid :suit current-suit} :info info}
   current-trick
   just-played]
  (let [new-suit (new-suit current-suit current-bid just-played)
        id-to-prompt (players/next-player (just-played :player) players)
        hand-to-prompt (-> |(= ($0 :id) id-to-prompt)
                           (find players)
                           (in :hand))
        play-prompt (->> (cards/of-suit-or-off new-suit current-bid hand-to-prompt)
                         (events/prompt-play id-to-prompt))]

    [{:phase "play"
      :info info
      :meta {:bid current-bid :suit new-suit}
      :stacks {:trick current-trick}}
     [(events/add-decoration (just-played :player)
                             "play_action"
                             (string "played " (cards/to-text just-played)))
      play-prompt]]))

## Continue the Hand
(defn- continue-hand [events info current-bid winning-player]
  (array/push events (events/prompt-play winning-player))
  # State: Play->Play


@@ 103,17 111,19 @@
     :stacks @{:trick []}}
   events])

## End the Hand
(defn- next-hand [players events info current-bid]
  (let [total-tricks (total-tricks players current-bid info)
        score-multiplier (adjustment-for-bid current-bid)
        opponent-team-keyword (-> players (non-bidding-team current-bid) (keyword))
        opponents-score (in info opponent-team-keyword)
        bidding-team-keyword (-> players (bidding-team current-bid) (keyword))
        bidders-score (in info bidding-team-keyword)
        bidders-score (if (made-bid? total-tricks current-bid)
                        (+ bidders-score (-> total-tricks (tricks-value) (score-multiplier)))
                        (- bidders-score (-> current-bid (in :count) (score-multiplier) )))]
    
                        (- bidders-score (-> current-bid (in :count)
			(score-multiplier) )))
        opponent-team-keyword (-> players (non-bidding-team current-bid) (keyword))
        opponents-score (in info opponent-team-keyword)]
            
    (if (or (won? bidders-score) (lost? bidders-score))
      (array/push events (events/end-game players
                                          bidding-team-keyword


@@ 126,6 136,7 @@
              bidding-team-keyword bidders-score}}
     events]))

## End the Trick
(defn- end-trick
  ```
  Handle the last player playing to a trick.


@@ 148,6 159,8 @@
      0 (next-hand players events updated-info current-bid)
      (continue-hand events updated-info current-bid winning-player))))

## Main Play Function
(defn- add-to-stack [stack card] (tuple ;stack card))

(defn play-phase
  ```


@@ 173,3 186,5 @@
    (case (length current-trick)
      4 (end-trick players state current-trick)
      (continue-trick players state current-trick just-played))))



M whist.lit => whist.lit +22 -0
@@ 1007,4 1007,26 @@ player ID to their final score.
					[score1 score1 score2 score2])}))
---

@s play.janet

Having covered all the possible outcomes of a play state transition,
we can wrap up all the components into a single module.

--- game/play.janet
(import cards)
(import players)
(import events)
# Play utility logic
@{New Suit}
@{Total Tricks}
@{Bid Values}
@{Made Bid?}
# Possible branches of a play state transition
@{Continue the Trick}
@{Continue the Hand}
@{End the Hand}
@{End the Trick}
@{Main Play Function}
---

@include lit/events.lit
\ No newline at end of file