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:
|
||||
- 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Phases []Phase
|
||||
Hands []Hand
|
||||
Deck Deck
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue