master
Bel LaPointe 2021-03-28 13:13:17 -05:00
parent 117250f5c1
commit 9efb30ae3e
9 changed files with 269 additions and 6 deletions

View File

@ -1,4 +1,4 @@
# after each phase, given game, evaluate if end # after each player op, given game, evaluate if end
end: end:
- op: playerCount - op: playerCount
operand: 1 operand: 1
@ -12,10 +12,6 @@ phases:
operand: 5 operand: 5
- op: bet - op: bet
- op: end - 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 # TODO: inverted ranking, I think negative is enough
hands: hands:
- royalFlush - royalFlush
@ -29,5 +25,8 @@ hands:
- pair - pair
- highCard - highCard
deck: deck:
exclude: aceLow: false
withoutValue:
- joker - joker
withoutSuit:
- heart

5
src/game/rule/deck.go Normal file
View File

@ -0,0 +1,5 @@
package rule
import "local/sandbox/cards/src/game/rule/operation"
type Deck operation.Cards

View File

@ -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
}

View File

@ -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) {
})
}
}

View File

@ -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
}

View File

@ -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))
}
}

View File

@ -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
}

View File

@ -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))
}
}

View File

@ -4,4 +4,5 @@ type Rule struct {
Ends []End Ends []End
Phases []Phase Phases []Phase
Hands []Hand Hands []Hand
Deck Deck
} }