in prog
parent
117250f5c1
commit
9efb30ae3e
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package rule
|
||||||
|
|
||||||
|
import "local/sandbox/cards/src/game/rule/operation"
|
||||||
|
|
||||||
|
type Deck operation.Cards
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -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) {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,4 +4,5 @@ type Rule struct {
|
||||||
Ends []End
|
Ends []End
|
||||||
Phases []Phase
|
Phases []Phase
|
||||||
Hands []Hand
|
Hands []Hand
|
||||||
|
Deck Deck
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue