From 9efb30ae3e6865a29c46868572ab0d854abf2403 Mon Sep 17 00:00:00 2001 From: Bel LaPointe Date: Sun, 28 Mar 2021 13:13:17 -0500 Subject: [PATCH] in prog --- games/poker.yaml | 11 ++-- src/game/rule/deck.go | 5 ++ src/game/rule/operation/cards.go | 56 ++++++++++++++++++++ src/game/rule/operation/cards_test.go | 29 +++++++++++ src/game/rule/operation/suit.go | 52 +++++++++++++++++++ src/game/rule/operation/suit_test.go | 24 +++++++++ src/game/rule/operation/value.go | 73 +++++++++++++++++++++++++++ src/game/rule/operation/value_test.go | 24 +++++++++ src/game/rule/rule.go | 1 + 9 files changed, 269 insertions(+), 6 deletions(-) create mode 100644 src/game/rule/deck.go create mode 100644 src/game/rule/operation/cards.go create mode 100644 src/game/rule/operation/cards_test.go create mode 100644 src/game/rule/operation/suit.go create mode 100644 src/game/rule/operation/suit_test.go create mode 100644 src/game/rule/operation/value.go create mode 100644 src/game/rule/operation/value_test.go diff --git a/games/poker.yaml b/games/poker.yaml index 0494d9e..3c49121 100644 --- a/games/poker.yaml +++ b/games/poker.yaml @@ -1,4 +1,4 @@ -# after each phase, given game, evaluate if end +# after each player op, given game, evaluate if end end: - op: playerCount operand: 1 @@ -12,10 +12,6 @@ phases: operand: 5 - op: bet - op: end -# always return an number type (or zero if not qualified) w/ high card -# ie -# two pair and a card -# king, king, 4, 4, 3 => 1000 * (13) + 10 * (4) + 3 = 1343 # TODO: inverted ranking, I think negative is enough hands: - royalFlush @@ -29,5 +25,8 @@ hands: - pair - highCard deck: - exclude: + aceLow: false + withoutValue: - joker + withoutSuit: + - heart diff --git a/src/game/rule/deck.go b/src/game/rule/deck.go new file mode 100644 index 0000000..d0eeba5 --- /dev/null +++ b/src/game/rule/deck.go @@ -0,0 +1,5 @@ +package rule + +import "local/sandbox/cards/src/game/rule/operation" + +type Deck operation.Cards diff --git a/src/game/rule/operation/cards.go b/src/game/rule/operation/cards.go new file mode 100644 index 0000000..fad4bf1 --- /dev/null +++ b/src/game/rule/operation/cards.go @@ -0,0 +1,56 @@ +package operation + +import "local/sandbox/cards/src/entity" + +type Cards struct { + AceLow bool + WithoutValue []Value + WithoutSuit []Suit +} + +func (cards Cards) NewDeck() entity.Deck { + deck := new54DeckAceHigh() + if cards.AceLow { + deck = new54DeckAceLow() + } + for i := len(deck.Deck) - 1; i >= 0; i-- { + card := deck.Deck[i] + drop := false + for _, value := range cards.WithoutValue { + drop = drop || card.Value == int(value) + } + for _, suit := range cards.WithoutSuit { + drop = drop || card.Suit == int(suit) + } + if drop { + deck.Deck = append(deck.Deck[:i], deck.Deck[i+1:]...) + } + } + return deck +} + +func new54DeckAceHigh() entity.Deck { + cards := make([]entity.Card, 0, 54) + for _, suit := range suitStrings { + for _, value := range valueStrings { + if value != AceLow && value != Joker { + cards = append(cards, entity.Card{Suit: int(suit), Value: int(value)}) + } + } + } + cards = append(cards, entity.Card{Value: int(Joker)}) + cards = append(cards, entity.Card{Value: int(Joker)}) + deck := entity.Deck{Deck: cards} + deck.Shuffle() + return deck +} + +func new54DeckAceLow() entity.Deck { + deck := new54DeckAceHigh() + for i, card := range deck.Deck { + if card.Value == int(AceHigh) { + deck.Deck[i].Value = int(AceLow) + } + } + return deck +} diff --git a/src/game/rule/operation/cards_test.go b/src/game/rule/operation/cards_test.go new file mode 100644 index 0000000..7c75cef --- /dev/null +++ b/src/game/rule/operation/cards_test.go @@ -0,0 +1,29 @@ +package operation + +import "testing" + +func TestNewDeck54(t *testing.T) { + deck := new54DeckAceLow() + if len(deck.Deck) != 54 { + t.Fatal(len(deck.Deck)) + } + for _, card := range deck.Deck { + if card.Value == int(AceHigh) { + t.Fatal(card) + } + } +} + +func TestCardsNewDeck(t *testing.T) { + cases := map[string]struct { + cards Cards + check func(Cards) bool + }{} + + t.Fatal("not impl") + for name, d := range cases { + c := d + t.Run(name, func(t *testing.T) { + }) + } +} diff --git a/src/game/rule/operation/suit.go b/src/game/rule/operation/suit.go new file mode 100644 index 0000000..7ed8df3 --- /dev/null +++ b/src/game/rule/operation/suit.go @@ -0,0 +1,52 @@ +package operation + +import ( + "encoding/json" + "local/sandbox/cards/src/entity" +) + +type Suit int + +const ( + _ Suit = iota + Heart Suit = iota + Spade Suit = iota + Diamond Suit = iota + Club Suit = iota +) + +var suitStrings = map[string]Suit{ + "heart": Heart, + "spade": Spade, + "diamond": Diamond, + "club": Club, +} + +func (suit Suit) Is(card entity.Card) bool { + return card.Suit == int(suit) +} + +func (suit Suit) MarshalJSON() ([]byte, error) { + for k, v := range suitStrings { + if suit == v { + return json.Marshal(k) + } + } + return json.Marshal("?") +} + +func (suit *Suit) UnmarshalJSON(b []byte) error { + var s string + err := json.Unmarshal(b, &s) + if err != nil { + return err + } + for k, v := range suitStrings { + if k == s { + *suit = v + return nil + } + } + *suit = 0 + return nil +} diff --git a/src/game/rule/operation/suit_test.go b/src/game/rule/operation/suit_test.go new file mode 100644 index 0000000..80ce9c1 --- /dev/null +++ b/src/game/rule/operation/suit_test.go @@ -0,0 +1,24 @@ +package operation + +import ( + "encoding/json" + "local/sandbox/cards/src/entity" + "testing" +) + +func TestSuit(t *testing.T) { + var s Suit + if err := json.Unmarshal([]byte(`"heart"`), &s); err != nil { + t.Fatal(err) + } else if s != Heart { + t.Fatal(Heart, s) + } else if b, err := json.Marshal(s); err != nil { + t.Fatal(err) + } else if string(b) != `"heart"` { + t.Fatal(`"heart"`, string(b)) + } else if card := (entity.Card{Suit: int(Heart)}); !s.Is(card) { + t.Fatal(true, s.Is(card)) + } else if card := (entity.Card{Suit: int(Diamond)}); s.Is(card) { + t.Fatal(false, s.Is(card)) + } +} diff --git a/src/game/rule/operation/value.go b/src/game/rule/operation/value.go new file mode 100644 index 0000000..8c0aff5 --- /dev/null +++ b/src/game/rule/operation/value.go @@ -0,0 +1,73 @@ +package operation + +import ( + "encoding/json" + "local/sandbox/cards/src/entity" +) + +type Value int + +const ( + Joker Value = iota - 1 + AceLow Value = iota + Two Value = iota + Three Value = iota + Four Value = iota + Five Value = iota + Six Value = iota + Seven Value = iota + Eight Value = iota + Nine Value = iota + Ten Value = iota + Jack Value = iota + Queen Value = iota + King Value = iota + AceHigh Value = iota +) + +var valueStrings = map[string]Value{ + "joker": Joker, + "aceLow": AceLow, + "two": Two, + "three": Three, + "four": Four, + "five": Five, + "six": Six, + "seven": Seven, + "eight": Eight, + "nine": Nine, + "ten": Ten, + "jack": Jack, + "queen": Queen, + "king": King, + "aceHigh": AceHigh, +} + +func (value Value) Is(card entity.Card) bool { + return card.Value == int(value) +} + +func (value Value) MarshalJSON() ([]byte, error) { + for k, v := range valueStrings { + if value == v { + return json.Marshal(k) + } + } + return json.Marshal("?") +} + +func (value *Value) UnmarshalJSON(b []byte) error { + var s string + err := json.Unmarshal(b, &s) + if err != nil { + return err + } + for k, v := range valueStrings { + if k == s { + *value = v + return nil + } + } + *value = 0 + return nil +} diff --git a/src/game/rule/operation/value_test.go b/src/game/rule/operation/value_test.go new file mode 100644 index 0000000..8f52ea2 --- /dev/null +++ b/src/game/rule/operation/value_test.go @@ -0,0 +1,24 @@ +package operation + +import ( + "encoding/json" + "local/sandbox/cards/src/entity" + "testing" +) + +func TestValue(t *testing.T) { + var v Value + if err := json.Unmarshal([]byte(`"jack"`), &v); err != nil { + t.Fatal(err) + } else if v != Jack { + t.Fatal(Jack, v) + } else if b, err := json.Marshal(v); err != nil { + t.Fatal(err) + } else if string(b) != `"jack"` { + t.Fatal(`"jack"`, string(b)) + } else if card := (entity.Card{Value: int(Jack)}); !v.Is(card) { + t.Fatal(true, v.Is(card)) + } else if card := (entity.Card{Value: int(Four)}); v.Is(card) { + t.Fatal(false, v.Is(card)) + } +} diff --git a/src/game/rule/rule.go b/src/game/rule/rule.go index 2bf390c..cdc121a 100644 --- a/src/game/rule/rule.go +++ b/src/game/rule/rule.go @@ -4,4 +4,5 @@ type Rule struct { Ends []End Phases []Phase Hands []Hand + Deck Deck }