~subsetpark/whist

ref: 6c4b421ce2c269a6a4a4048cb7cd6f0712ff3c7e whist/game/bid.janet -rw-r--r-- 3.0 KiB
6c4b421c — Zach Smith Bug fix play->play transition, and dont emit discard event 7 months 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
(import players)
(import bids)
(import events)

(defn- new-meta
  [{:meta meta} {:value last-bid :player last-bidder}]
  (let [{:bid previous-high-bid :player previous-high-bidder} (meta :high_bid)
	# Record the high bid (whether it's a new bid or the existing high bid).
	[high-bid high-bidder] (case last-bid
				 "pass" [previous-high-bid previous-high-bidder]
				 [last-bid last-bidder])]
    @{:high_bid @{:player high-bidder :bid high-bid}}))

(defn- initial-events
  [{:meta {:high_bid {:bid previous-high-bid :player previous-high-bidder}}}
   {:value last-bid :player last-bidder}
   current-high-bid]
  (case last-bid
    "pass" @[(events/add-decoration last-bidder "bid_action" "passed")]
    (array/concat 
     (case previous-high-bidder
       nil @[]
       @[(events/clear-decoration previous-high-bidder "bid_action")])
     (events/add-decoration last-bidder "bid_action" "declarer")
     (events/add-decoration last-bidder "bid" (bids/to-text current-high-bid)))))

(defn- update-not-passed
  [{:meta {:not_passed not-passed}} {:value last-bid :player last-bidder}]
  (case last-bid
    # Handle a new pass. Mark the player as passed by removing them from the set.
    "pass" (put not-passed (keyword last-bidder) nil))
    not-passed)

(defn bid-phase
  ```
  The players bid in an auction to name trump. 

  The highest bid is a number of tricks to take above six with a named
  suit or no-trumps.
  
  Requires:
  - `high_bid`
  - `not_passed`: The players that haven't yet passed.
  ```
  [state players action]
  (if (= action :null) (error {:error "action required"}))
  (let  [new-meta (new-meta state action)
	 {:high_bid {:player high-bidder :bid high-bid}} new-meta
	 events (initial-events state action high-bid)
	 not-passed (update-not-passed state action)]
    # The set of players still in the auction is now up to date. We'll
    # use it to determine whether the action is over.
    (if (and (not (nil? high-bidder)) (= 1 (length not-passed)))
      # If someone has bid and all but one have passed, the auction is over.
      [(merge state {:meta new-meta
		     # State: Bid -> Discard
		     :phase "discard"})
       # Bidder selects suit in a trumps bid or direction in a no-trumps bid.
       (array/push events (events/pick1 "bid" high-bidder (bids/second-bid high-bid)))]
      # Otherwise, continue the bidding.
      (let [{:player last-bidder} action
	    next-bidder (players/next-player last-bidder players not-passed)]
	(array/push events (events/add-decoration next-bidder "bid_action" "bidding"))
	# The auction isn't over; include the set of players still bidding in the metadata.
	[(merge state {:meta (put new-meta :not_passed not-passed)
		       # State: Bid -> Bid
		       :phase "bid"})
	 (if (= 1 (length not-passed))
	   # If no one has bid and all but one have passed, the dealer has to bid.
	   (array/push events (events/pick1 "bid" next-bidder (bids/force-bid)))
	   # Otherwise, move to the next bidder.
	   (array/push events (events/pick1 "bid" next-bidder (bids/available-bids high-bid))))]))))