@@ 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))))
+
+
@@ 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