2024-01-07 00:09:47 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"math/rand"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Suit int
|
|
|
|
|
|
|
|
func (s Suit) String() string {
|
|
|
|
switch s {
|
|
|
|
case 0:
|
|
|
|
return "♠"
|
|
|
|
case 1:
|
|
|
|
return "♥"
|
|
|
|
case 2:
|
|
|
|
return "♦"
|
|
|
|
case 3:
|
|
|
|
return "♣"
|
|
|
|
case 4:
|
|
|
|
return "★"
|
|
|
|
default:
|
|
|
|
panic("bad suit")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type Card int
|
|
|
|
|
|
|
|
func (c Card) Joker() bool {
|
|
|
|
return (c == 0)
|
|
|
|
}
|
|
|
|
|
2024-01-07 01:51:06 +00:00
|
|
|
func (c Card) Masked() bool {
|
|
|
|
return (c == -1)
|
|
|
|
}
|
|
|
|
|
2024-01-07 00:09:47 +00:00
|
|
|
func (c Card) Suit() Suit {
|
2024-01-07 01:51:06 +00:00
|
|
|
if c.Joker() || c.Masked() {
|
|
|
|
panic("Suit on invalid")
|
|
|
|
}
|
|
|
|
|
2024-01-07 00:09:47 +00:00
|
|
|
return Suit(int(c) % 5)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c Card) Face() int {
|
2024-01-07 01:51:06 +00:00
|
|
|
if c.Joker() || c.Masked() {
|
|
|
|
panic("Face on invalid")
|
|
|
|
}
|
|
|
|
|
2024-01-07 00:09:47 +00:00
|
|
|
return int(c) / 5
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c Card) String() string {
|
|
|
|
if c.Joker() {
|
|
|
|
return "Jok" // 🂿 U+1F0BF
|
|
|
|
}
|
|
|
|
|
2024-01-07 01:51:06 +00:00
|
|
|
if c.Masked() {
|
2024-01-07 00:09:47 +00:00
|
|
|
return "INV" // Invalid
|
|
|
|
}
|
|
|
|
|
|
|
|
switch c.Face() {
|
|
|
|
case 11:
|
|
|
|
return fmt.Sprintf(" J%s", c.Suit().String())
|
|
|
|
|
|
|
|
case 12:
|
|
|
|
return fmt.Sprintf(" Q%s", c.Suit().String())
|
|
|
|
|
|
|
|
case 13:
|
|
|
|
return fmt.Sprintf(" K%s", c.Suit().String())
|
|
|
|
|
|
|
|
default:
|
|
|
|
return fmt.Sprintf("%2d%s", c.Face(), c.Suit().String())
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-01-07 01:51:06 +00:00
|
|
|
func NewMasked() Card {
|
|
|
|
return Card(-1)
|
|
|
|
}
|
|
|
|
|
2024-01-07 00:09:47 +00:00
|
|
|
func NewJoker() Card {
|
|
|
|
return Card(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewCardFrom(face int, suit Suit) Card {
|
|
|
|
return Card(face*5 + int(suit))
|
|
|
|
}
|
|
|
|
|
2024-01-07 02:33:45 +00:00
|
|
|
func Shuffle(c []Card, entropy *rand.Rand) {
|
|
|
|
entropy.Shuffle(len(c), func(i, j int) {
|
2024-01-07 00:09:47 +00:00
|
|
|
c[i], c[j] = c[j], c[i]
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-01-07 01:51:06 +00:00
|
|
|
const DeckSize = 58 * 2
|
|
|
|
|
2024-01-07 00:09:47 +00:00
|
|
|
func Deck() []Card {
|
|
|
|
// The full game deck is two 58-card decks
|
|
|
|
// Each 58-card deck has 3 jokers plus {3..10 J Q K} in 5 suits.
|
2024-01-07 01:51:06 +00:00
|
|
|
ret := make([]Card, 0, DeckSize)
|
2024-01-07 00:09:47 +00:00
|
|
|
for i := 0; i < 6; i++ {
|
|
|
|
ret = append(ret, NewJoker()) // Joker
|
|
|
|
}
|
|
|
|
|
|
|
|
for s := 0; s < 5; s++ {
|
|
|
|
for f := 3; f < 14; f++ {
|
|
|
|
ret = append(ret, NewCardFrom(f, Suit(s)), NewCardFrom(f, Suit(s)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret
|
|
|
|
}
|