You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

171 lines
3.0 KiB

package cribbage
import (
"fmt"
"math/rand"
"gioui.org/example/outlay/fan/playing"
)
type Phase uint8
const (
BetweenHands Phase = iota
Dealing
Sacrifice
Cut
CircularCount
CountHands
CountCrib
)
func (p Phase) String() string {
switch p {
case BetweenHands:
return "between"
case Dealing:
return "dealing"
case Sacrifice:
return "sacrifice"
case Cut:
return "cut"
case CircularCount:
return "circular count"
case CountHands:
return "count hands"
case CountCrib:
return "count crib"
default:
return "unknown"
}
}
type Game struct {
Phase
Deck []playing.Card
CutCard *playing.Card
Dealer int
Crib []playing.Card
Players []Player
}
type Player struct {
Hand, Table []playing.Card
}
func (p Player) String() string {
return fmt.Sprintf("[Hand: %s, Table: %s]", p.Hand, p.Table)
}
func (g Game) String() string {
return fmt.Sprintf("[Phase: %v\nDealer: %v\nCrib: %v\nCut: %v\nPlayers: %v\nDeck: %v]\n", g.Phase, g.Dealer, g.Crib, g.CutCard, g.Players, g.Deck)
}
const MinHand = 4
func NewGame(players int) Game {
var g Game
g.Players = make([]Player, players)
g.Dealer = g.NumPlayers() - 1
for i := 0; i < 4; i++ {
for j := 0; j < 13; j++ {
g.Deck = append(g.Deck, playing.Card{
Suit: playing.Suit(i),
Rank: playing.Rank(j),
})
}
}
g.Phase = Dealing
return g
}
func (g Game) NumPlayers() int {
return len(g.Players)
}
func (g Game) Right(player int) int {
return (player + g.NumPlayers() - 1) % g.NumPlayers()
}
func (g Game) Left(player int) int {
return (player + 1) % g.NumPlayers()
}
func (g *Game) CutAt(depth int) {
g.CutCard = &g.Deck[depth]
g.Phase = CircularCount
}
func DrainInto(src, dest *[]playing.Card) {
for _, c := range *src {
*dest = append(*dest, c)
}
*src = (*src)[:0]
}
func (g *Game) Reset() {
for i := range g.Players {
DrainInto(&(g.Players[i].Hand), &g.Deck)
DrainInto(&(g.Players[i].Table), &g.Deck)
}
DrainInto(&(g.Crib), &g.Deck)
g.Phase = Dealing
g.CutCard = nil
}
func (g *Game) DealCardTo(dest *[]playing.Card) {
card := g.Deck[0]
g.Deck = g.Deck[1:]
*dest = append(*dest, card)
}
func (g *Game) DealRound() {
g.Dealer = g.Left(g.Dealer)
g.Reset()
g.Shuffle()
for i := 0; i < g.CardsToDealPerPlayer(); i++ {
for i := range g.Players {
g.DealCardTo(&(g.Players[i].Hand))
}
}
for i := 0; i < g.CardsDealtToCrib(); i++ {
g.DealCardTo(&g.Crib)
}
g.Phase = Sacrifice
}
func (g Game) CardsToDealPerPlayer() int {
switch g.NumPlayers() {
case 2:
return 6
case 3:
return 5
case 4:
return 5
default:
return 0
}
}
func (g Game) CardsDealtToCrib() int {
if g.NumPlayers() == 3 {
return 1
}
return 0
}
func (g *Game) Shuffle() {
rand.Shuffle(len(g.Deck), func(i, j int) {
g.Deck[i], g.Deck[j] = g.Deck[j], g.Deck[i]
})
}
func (g *Game) Sacrifice(player, card int) {
hand := g.Players[player].Hand
if len(hand) <= MinHand {
return
}
c := hand[card]
g.Players[player].Hand = append(hand[:card], hand[card+1:]...)
g.Crib = append(g.Crib, c)
}