In a scary number of previous posts I have talked about modeling a bidding system for bridge. But so far, we have only designed the part where one player looks at their hand and decides what to do. But, as always, the reality is more complex. The bidding of course is an interaction between two partners. I say something, and based on that bid and their cards, my partner is going to answer. So, after the initial bid (called opening bid) the system should also take the history into account.
Trees with shared subtrees
This in effect means that the system is a tree, but the issue is that there are lots of shared subtrees. Suppose I bid one of Clubs, and my partner has no (strong) Clubs, they will bid their favorite color. But they will do so too when I bid Hearts and they have none. I tried a few options until I settled on what I now think is okay. As I explained here I started with just tuples of Conditions and Bids:
type BiddingSystem = list<Condition * Bid>
Attempt #2 – States for bids
But that clearly does not support the nested structure we need. The first attempt at the trees was to thing to attach a bidding state to all bids. Some would be open, others would be answer1 etc.
We would then get:
type BiddingSystem = list<Condition * State * Bid>
and a rule would be
(both (points 15 17) (forAllSuits (cards 2 13)), Open, Bid (1, SA))
Based on the history of the bids, we would determine whether a state was available:
let rec stateAvailable (p:Player) (s:State) (history:BidHistory) : bool = match s with //if no one has opened yet (i.e. only passes have occured) we may do so | Open -> not (List.exists (fun (x,b) -> b <> Pass) history) //we can only answer if our partner has already bid | Answer -> List.exists (fun (x,b) -> x = partner p) history
This worked for a few of the smaller cases, but you would need lots of different states, and, I could not refer back to the bid of my partner (as in: raise the color they bid with one step. So, nah, not really nice.
Attempt #3 – Modeling trees as real trees
Okay, the above had several issues, mainly the referral issue. So, what if we just model them really as trees? I changed the type of the BiddingSystem into
BiddingSystem = (Condition * Bid * BiddingSystem) list
Now, a rule in the system results in a Bid and a resulting system, that you pass to the answerer to use. A rule looked something like this:
(both (points 12 19) (cards 4 13 Clubs) , Bid (1, Clubs), //answers to a one bid here: (points 6 9, Bid (2, Clubs), Empty) )
Okay, this is surely nicer than the option above as we do not need to check anymore whether a bid fits. But the issue still is duplication, many of the nested rules would be similar and that would be 1) boring to type and 2) hard to change. What will be real solution be? Stay tuned! Putting it in this post would make it too long 🙂