Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ Here is a rough summary of some of the data types in the code:
select which `Topic`s you want to practice.
- A `Description` is a string-like data type that can render certain things
(e.g., bids) in a fancy way. Most string-like things in here are actually
`Description`s (`Topic` names, bidding alerts, explanations of why the answer
`Description`s (bidding alerts, `Topic` names, explanations of why the answer
is correct, etc.).
- An `Action` is a way to modify either the `dealer` program or the bidding.
The embedded domain-specific language I've built is entirely made out of
Expand Down
4 changes: 1 addition & 3 deletions make_pdf/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ main = let
, Lampe.topic
, TripleFourOne.topic
]
topics = [ MajorSuitRaises.topic
, ForcingOneNotrump.topic
, Jacoby2NT.topic
topics = [ Lebensohl.topic
]
in do
-- outputLatex returns a copy of the contents of the file it wrote, but we
Expand Down
86 changes: 68 additions & 18 deletions src/Bids/Lebensohl.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,26 @@ module Bids.Lebensohl(
, b1No2C2D
, b1No2C2H
-- Actual lebensohl bids
, bLebensohl2N
, bLebensohl3C
, b1No2C3D
, b1No2C3H
, b1No2C3S
, b1No2D2H
, b1No2D2S
, b1No2D2N3CP
, b1No2D3C
, b1No2D3H
, b1No2D3S
, b1No2H2S
, b1No2H2N3CP
, b1No2H2N3C3D
, b1No2H3C
, b1No2H3D
, b1No2H3S
, b1No2S2N3CP
, b1No2S2N3C3D
, b1No2S2N3C3H
, b1No2S3C
, b1No2S3D
, b1No2S3H
Expand All @@ -29,8 +37,10 @@ module Bids.Lebensohl(

import Action(Action, withholdBid)
import qualified Bids.OneNotrump as NT
import EDSL(minSuitLength, makeCall, longerThan, atLeastAsLong, pointRange,
forbid, balancedHand, hasStopper, alternatives, soundHolding)
import EDSL(minSuitLength, makeCall, makeAlertableCall, pointRange, forEach,
forbid, balancedHand, hasStopper, alternatives, soundHolding,
longerThan, atLeastAsLong)
import Output((.+))
import qualified Terminology as T


Expand Down Expand Up @@ -61,32 +71,29 @@ b1No2C2H :: Action
b1No2C2H = NT.b1N2H

-- Signoffs
b1No2D2H :: Action
b1No2D2H = do
signoff_ :: Int -> T.Suit -> Action
signoff_ level suit = do
NT.lessThanInvitational
pointRange 5 40
minSuitLength T.Hearts 5
minSuitLength suit 5
-- Have a good reason to bid this suit.
alternatives [soundHolding suit, minSuitLength suit 6]
-- If you're 5-5 in the majors, pick the better suit. I'm too lazy to add
-- something to the EDSL to figure out which suit is better, so avoid it.
T.Hearts `longerThan` T.Clubs
T.Hearts `longerThan` T.Diamonds
T.Hearts `longerThan` T.Spades
makeCall $ T.Bid 2 T.Hearts
forEach (filter (/= suit) T.allSuits) (suit `longerThan`)
makeCall $ T.Bid level suit


b1No2D2H :: Action
b1No2D2H = signoff_ 2 T.Hearts


b1No2D2S :: Action
b1No2D2S = do
NT.lessThanInvitational
pointRange 5 40
minSuitLength T.Spades 5
T.Spades `longerThan` T.Clubs
T.Spades `longerThan` T.Diamonds
T.Spades `longerThan` T.Hearts
makeCall $ T.Bid 2 T.Spades
b1No2D2S = signoff_ 2 T.Spades


b1No2H2S :: Action
b1No2H2S = b1No2D2S
b1No2H2S = signoff_ 2 T.Spades


primarySuit_ :: T.Suit -> Action
Expand Down Expand Up @@ -159,3 +166,46 @@ b1No2D3S = gfWithSuit_ T.Spades T.Diamonds

b1No2H3S :: Action
b1No2H3S = gfWithSuit_ T.Spades T.Hearts


-- This is the meat of lebensohl!
bLebensohl2N :: Action
bLebensohl2N = do
alternatives [ b1No2D2N3CP
, b1No2H2N3CP
, b1No2S2N3CP
, b1No2H2N3C3D
, b1No2S2N3C3D
, b1No2S2N3C3H
]
makeAlertableCall (T.Bid 2 T.Notrump) ("relay to " .+ T.Bid 3 T.Clubs)


bLebensohl3C :: Action
bLebensohl3C = makeAlertableCall (T.Bid 3 T.Clubs) "relay completed"


-- Signoffs that you couldn't bid at the 2 level
b1No2D2N3CP :: Action
b1No2D2N3CP = do
withholdBid $ signoff_ 8 T.Clubs
makeCall T.Pass

b1No2H2N3CP :: Action
b1No2H2N3CP = do
withholdBid $ signoff_ 8 T.Clubs
makeCall T.Pass

b1No2S2N3CP :: Action
b1No2S2N3CP = do
withholdBid $ signoff_ 8 T.Clubs
makeCall T.Pass

b1No2H2N3C3D :: Action
b1No2H2N3C3D = signoff_ 3 T.Diamonds

b1No2S2N3C3D :: Action
b1No2S2N3C3D = signoff_ 3 T.Diamonds

b1No2S2N3C3H :: Action
b1No2S2N3C3H = signoff_ 3 T.Hearts
63 changes: 55 additions & 8 deletions src/Topics/Lebensohl.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ module Topics.Lebensohl(topic) where

import Control.Monad(join)

import Action(extractLastCall, withholdBid)
import qualified Bids.Cappelletti as Capp
import qualified Bids.DONT as DONT
import qualified Bids.Lebensohl as Leb
import qualified Bids.Meckwell as MW
import qualified Bids.NaturalOneNotrumpDefense as Nat
import CommonBids(setOpener)
--import EDSL(makePass, pointRange, suitLength, maxSuitLength, forEach)
import Output((.+))
import Output(Description, (.+))
import Situation(situation, (<~))
import qualified Terminology as T
import Topic(Topic, wrap, Situations, makeTopic)
Expand Down Expand Up @@ -58,8 +59,8 @@ ignoreOpps = let
<~ T.allVulnerabilities


signoff :: Situations
signoff = let
signoff2 :: Situations
signoff2 = let
sit (overcall, response) = let
action = do
setOpener T.North
Expand All @@ -70,7 +71,7 @@ signoff = let
"with the auction. We're so weak we don't even want to invite " .+
"to game, but we do have enough strength to suspect this is " .+
"our contract. Bid our suit at the 2 level, as signoff."
in situation "snof" action response explanation
in situation "so2" action response explanation
in
wrap $ return sit <~ [ (DONT.b1No2D, Leb.b1No2D2H)
, (DONT.b1No2D, Leb.b1No2D2S)
Expand Down Expand Up @@ -130,15 +131,60 @@ gameForce = let
<~ T.allVulnerabilities


signoff3 :: Situations
signoff3 = let
sit (overcall, responses) dlr vul = let
inner response = let
action = do
setOpener T.North
Leb.b1N
_ <-overcall
withholdBid response
responseDescription :: Description
responseDescription =
if (T.removeAlert . extractLastCall $ response) == T.Pass
then "pass" .+ ""
else "bid " .+ response
explanation =
"Partner opened a strong " .+ Leb.b1N .+ ", and RHO " .+
"interfered with the auction. We're less-than-invitational, " .+
"and just want to sign off in partscore. However, we can't " .+
"do that at the 2 level any more. Make a lebensohl relay, " .+
"planning to " .+ responseDescription .+ " afterwards."
in situation "so3" action Leb.bLebensohl2N explanation dlr vul
in return inner <~ responses
in
wrap . join $ return sit
<~ [ (Nat.b1No2D, [Leb.b1No2D2N3CP])
, (Nat.b1No2H, [Leb.b1No2H2N3CP, Leb.b1No2H2N3C3D])
, (Nat.b1No2S, [Leb.b1No2S2N3CP, Leb.b1No2S2N3C3D, Leb.b1No2S2N3C3H])
, (DONT.b1No2D, [Leb.b1No2D2N3CP])
-- Don't bid either major when the opponents have shown both
, (DONT.b1No2H, [Leb.b1No2H2N3CP, Leb.b1No2H2N3C3D])
, (DONT.b1No2S, [Leb.b1No2S2N3CP, Leb.b1No2S2N3C3D, Leb.b1No2S2N3C3H])
, (MW.b1No2D, [Leb.b1No2D2N3CP])
, (MW.b1No2H, [Leb.b1No2H2N3CP, Leb.b1No2H2N3C3D])
, (MW.b1No2S, [Leb.b1No2S2N3CP, Leb.b1No2S2N3C3D, Leb.b1No2S2N3C3H])
-- Again, don't bid a major when RHO has them both. 3D should be
-- natural and not a cue bid, because you'd never want to have a
-- Stayman-like bid when RHO has shown both majors.
, (Capp.b1No2D, [Leb.b1No2D2N3CP, Leb.b1No2H2N3C3D])
, (Capp.b1No2H, [Leb.b1No2H2N3CP, Leb.b1No2H2N3C3D])
, (Capp.b1No2S, [Leb.b1No2S2N3CP, Leb.b1No2S2N3C3D, Leb.b1No2S2N3C3H])
]
-- East should be an unpassed hand to interfere.
<~ [T.North, T.South, T.West]
<~ T.allVulnerabilities


-- TODO:
-- natural GF bids at the 3 level
-- jump to 3N
-- relay to 3N (answer should be 2N planning to rebid 3N)
-- cue bid for Stayman
-- relay to cue bid (answer should be 2N planning to rebid the cue)
-- complete the relay
-- Texas transfers over interference (in the Texas Transfers topic)
-- make the opponents sometimes use natural overcalls
-- pass after relay and signoff
-- pass or bid game after relay and invite


topic :: Topic
Expand All @@ -147,6 +193,7 @@ topic = makeTopic
"leb1N" situations
where
situations = wrap [ ignoreOpps
, signoff
, signoff2
, signoff3
, gameForce
]