~subsetpark/whist

ref: b4197421dcbc4b6877e7b574a1fc6ee2802d1171 whist/game/play.janet -rw-r--r-- 3.2 KiB
b4197421 — Zach Smith Replace add_score with info boxes 1 year, 1 month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
(import cards)
(import players)
(import events)
 
(defn- add-to-stack [stack card] (tuple ;stack card))
(defn- with-player [card player] (merge-into @{:player player} card))
(defn- new-suit
  ```
  Determine the led suit in a given trick.

  - If the suit has already been determined, use that.
  - If the card isn't a joker, the led suit is the suit of that card.
  - If the card is a joker :
    - If the bid is notrumps, the led suit hasn't been determined yet.
    - Otherwise, the led suit is the trump suit.
  ```
  [current-suit bid card-played]
  (if (not= current-suit :null)
    current-suit
    (match [(bid :suit) (card-played :suit)]
      ["notrumps" "joker"] :null
      [trumps "joker"] trumps
      [_ led-suit] led-suit)))

(defn- prompt-play [player from]
  {:event "prompt_play" :player player :to "trick" :count 1 :from from})

(defn play-phase
  ```
  Players play to tricks.
  
  In the first trick, the bidder leads; every subsequent trick, the
  winner of the previous trick leads.

  Players must follow suit if possible; if not, they can either
  discard or trump.

  Expected stacks:
  - `trick`: The current trick.
  Expected metadata:
  - `bid`: The current contract.
  - `suit`: The led suit of the current trick.
  ```
  [old-state players {:player player :value card}]
  # We need to explicitly set the current suit to null. 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.
  (var new-state @{:info (old-state :info) :meta @{} :stacks @{}})
  (var events @[(events/add-decoration player "play_action" (string "played " (cards/to-text card)))])
  (let [current-trick (get-in old-state [:stacks :trick])
	current-bid (get-in old-state [:meta :bid])
	just-played (with-player card player)]
    (case (length current-trick)
      3 (let [apply-ordering (cards/apply-ordering current-bid)
	      full-trick (array ;current-trick just-played)
	      with-compare (map apply-ordering full-trick) 
	      current-suit (get-in old-state [:meta :suit])
	      highest (cards/high-card current-suit (current-bid :suit) ;with-compare)
	      highest-player (highest :player)]
	  (update-in new-state [:info (keyword highest-player "_tricks") :value] inc)
	  (case (length ((players 0) :hand)) 
	    # It's the last trick of the hand.
	    # TODO: reckon scores and reset
	    1 :ok
	     (let [player-to-prompt (find |(= ($0 :id) highest-player) players)
		   hand-to-prompt (player-to-prompt :hand)]
	       (put new-state :phase "play")
		   (put-in new-state [:stacks :trick] [])
		   (array/push events (prompt-play highest-player hand-to-prompt)))))
      (let [old-meta (old-state :meta)
	    current-suit (old-meta :suit)
	    new-suit (new-suit current-suit current-bid card)
	    id-to-prompt (players/next-player player players)
	    player-to-prompt (find |(= ($0 :id) id-to-prompt) players)]
	(put new-state :phase "play")
	(put-in new-state [:meta :suit] new-suit)
	(put-in new-state [:stacks :trick] (add-to-stack current-trick just-played))
	(array/push
	 events
	 (prompt-play id-to-prompt (cards/of-suit-or-off new-suit current-bid (player-to-prompt :hand))))))
    [new-state events]))