save
This commit is contained in:
parent
a5f78f4d9d
commit
95e6383f94
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"git.tuxpa.in/a/card_id/common/game"
|
"git.tuxpa.in/a/card_id/common/game"
|
||||||
"git.tuxpa.in/a/card_id/common/game/card"
|
"git.tuxpa.in/a/card_id/common/game/card"
|
||||||
|
"git.tuxpa.in/a/card_id/common/game/score"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -16,15 +17,27 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicln(err)
|
log.Panicln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
g := game.Game{Dealer: deal, Lives: 3}
|
g := game.Game{Dealer: deal, Lives: 3}
|
||||||
|
|
||||||
trial := g.CreateTrial(3, 1)
|
trial := g.CreateTrial(3, 1)
|
||||||
|
g.CurrentTrial = 1
|
||||||
|
fmt.Println("type c[n] to select a card, e.g. c1")
|
||||||
|
fmt.Println("exit to exit")
|
||||||
for {
|
for {
|
||||||
if trial != nil {
|
if trial != nil {
|
||||||
if trial.CheckSelection() {
|
sc, lives := trial.CheckSelection()
|
||||||
fmt.Print("\n match found!!!")
|
if sc != 0 {
|
||||||
|
fmt.Println(" match found!!!")
|
||||||
|
g.Combo = g.Combo + 1
|
||||||
|
g.Score = g.Score + sc*score.DefaultTable.Ratio(g.Combo)*g.CurrentTrial
|
||||||
|
} else {
|
||||||
|
g.Combo = 0
|
||||||
}
|
}
|
||||||
|
g.Lives = g.Lives + lives
|
||||||
|
msg := fmt.Sprintf(`
|
||||||
|
lives: %0.4v | score: %d | combo: %d
|
||||||
|
`, g.Lives, g.Score, g.Combo)
|
||||||
|
fmt.Printf(msg)
|
||||||
}
|
}
|
||||||
fmt.Printf("\ncardid > ")
|
fmt.Printf("\ncardid > ")
|
||||||
var args [4]string
|
var args [4]string
|
||||||
|
@ -45,20 +58,15 @@ func main() {
|
||||||
case "select", "sel", "c":
|
case "select", "sel", "c":
|
||||||
if alen > 1 {
|
if alen > 1 {
|
||||||
num, _ := strconv.Atoi(args[1])
|
num, _ := strconv.Atoi(args[1])
|
||||||
cd, err := trial.SelectCard(num)
|
_, err := trial.SelectCard(num)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
if cd.Id > 0 {
|
|
||||||
msg := fmt.Sprintf(`
|
|
||||||
card %d was %s | lives: %d
|
|
||||||
current hand:
|
|
||||||
%s`, num, cd.Name, trial.Lives, trial.ShowString())
|
|
||||||
fmt.Printf(msg)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
trial.SelectCard(0)
|
trial.SelectCard(0)
|
||||||
}
|
}
|
||||||
|
fmt.Printf("hand: %s\n", trial.ShowString())
|
||||||
case "debug":
|
case "debug":
|
||||||
fmt.Println(trial)
|
fmt.Println(trial)
|
||||||
case "exit", "quit", "q":
|
case "exit", "quit", "q":
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
package data
|
|
@ -1,16 +1,47 @@
|
||||||
package card
|
package card
|
||||||
|
|
||||||
import "git.tuxpa.in/a/card_id/common/data"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.tuxpa.in/a/card_id/common/data"
|
||||||
|
"lukechampine.com/frand"
|
||||||
|
)
|
||||||
|
|
||||||
type Card struct {
|
type Card struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
CleanName string `json:"clean_name"`
|
||||||
|
|
||||||
Rate float64 `json:"rate"`
|
Rate float64 `json:"rate"`
|
||||||
|
|
||||||
|
BonusLife bool `json:"bonus_life"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Card) FromResult(d data.Result) Card {
|
func (c *Card) FromResult(d data.Result) Card {
|
||||||
c.Id = d.Id
|
c.Id = d.Id
|
||||||
c.Name = d.Name
|
c.Name = d.Name
|
||||||
c.Rate = d.Rate
|
c.Rate = d.Rate
|
||||||
|
c.CleanName = strings.ReplaceAll(strings.TrimSpace(stripNum(c.Name)), " ", " ")
|
||||||
return *c
|
return *c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Card) CopyWithBonus(chance float64) Card {
|
||||||
|
return Card{
|
||||||
|
Id: c.Id,
|
||||||
|
Rate: c.Rate,
|
||||||
|
Name: c.Name,
|
||||||
|
CleanName: c.CleanName,
|
||||||
|
BonusLife: (frand.Float64() <= chance),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stripNum(s string) string {
|
||||||
|
var result strings.Builder
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
b := s[i]
|
||||||
|
if !('0' <= b && b <= '9') {
|
||||||
|
result.WriteByte(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.String()
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,25 @@ func NewDealer() *Dealer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Dealer) CardNames() []string {
|
||||||
|
out := map[string]struct{}{}
|
||||||
|
for _, br := range g.Brands {
|
||||||
|
for _, c := range br.RewardDeck.Cards {
|
||||||
|
out[c.CleanName] = struct{}{}
|
||||||
|
}
|
||||||
|
if br.SpecialDeck != nil {
|
||||||
|
for _, c := range br.SpecialDeck.Cards {
|
||||||
|
out[c.CleanName] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keys := make([]string, 0, len(out))
|
||||||
|
for k := range out {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
func (g *Dealer) ReadFromRoot(datadir string) (*Dealer, error) {
|
func (g *Dealer) ReadFromRoot(datadir string) (*Dealer, error) {
|
||||||
if datadir == "" {
|
if datadir == "" {
|
||||||
datadir = "./data"
|
datadir = "./data"
|
||||||
|
|
|
@ -13,10 +13,13 @@ type Deck struct {
|
||||||
Cards []Card
|
Cards []Card
|
||||||
|
|
||||||
TotalProbability float64
|
TotalProbability float64
|
||||||
|
|
||||||
|
BonusLifeProbability float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDeck(r data.Results) *Deck {
|
func NewDeck(r data.Results) *Deck {
|
||||||
out := &Deck{}
|
out := &Deck{}
|
||||||
|
out.BonusLifeProbability = 0.005
|
||||||
out.Cards = make([]Card, 0, len(r))
|
out.Cards = make([]Card, 0, len(r))
|
||||||
for _, v := range r {
|
for _, v := range r {
|
||||||
out.Cards = append(out.Cards, new(Card).FromResult(v))
|
out.Cards = append(out.Cards, new(Card).FromResult(v))
|
||||||
|
@ -31,7 +34,7 @@ func (t *Deck) Draw() Card {
|
||||||
for _, v := range t.Cards {
|
for _, v := range t.Cards {
|
||||||
sofar = sofar + v.Rate
|
sofar = sofar + v.Rate
|
||||||
if sofar >= selector-0.000000001 {
|
if sofar >= selector-0.000000001 {
|
||||||
return v
|
return v.CopyWithBonus(t.BonusLifeProbability)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Card{
|
return Card{
|
||||||
|
|
|
@ -6,8 +6,31 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Game struct {
|
type Game struct {
|
||||||
Lives int
|
Lives float64
|
||||||
Dealer *card.Dealer
|
Score int
|
||||||
|
|
||||||
|
Combo int
|
||||||
|
BestCombo int
|
||||||
|
CurrentTrial int
|
||||||
|
|
||||||
|
Trial *Trial
|
||||||
|
Trials []Trial
|
||||||
|
|
||||||
|
Player string
|
||||||
|
PlayerId string
|
||||||
|
|
||||||
|
Dealer *card.Dealer `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) New(user string, dealer *card.Dealer) *Game {
|
||||||
|
return &Game{
|
||||||
|
Dealer: dealer,
|
||||||
|
Player: user,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) Resolve(action string, args []string) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) CreateTrial(pairs int, extra int) *Trial {
|
func (g *Game) CreateTrial(pairs int, extra int) *Trial {
|
||||||
|
@ -37,7 +60,7 @@ func (g *Game) CreateTrial(pairs int, extra int) *Trial {
|
||||||
}
|
}
|
||||||
|
|
||||||
frand.Shuffle(len(cards), func(i, j int) { cards[i], cards[j] = cards[j], cards[i] })
|
frand.Shuffle(len(cards), func(i, j int) { cards[i], cards[j] = cards[j], cards[i] })
|
||||||
trial := NewTrial(g.Lives)
|
trial := NewTrial()
|
||||||
for k, v := range cards {
|
for k, v := range cards {
|
||||||
trial.Cards[k+1] = v
|
trial.Cards[k+1] = v
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package score
|
||||||
|
|
||||||
|
type ComboTable interface {
|
||||||
|
Ratio(int) int
|
||||||
|
}
|
||||||
|
|
||||||
|
type MapTable struct {
|
||||||
|
m map[int]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MapTable) Ratio(i int) int {
|
||||||
|
if v, ok := t.m[i]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var DefaultTable ComboTable = &MapTable{
|
||||||
|
m: map[int]int{
|
||||||
|
0: 1,
|
||||||
|
1: 2,
|
||||||
|
2: 4,
|
||||||
|
3: 7,
|
||||||
|
4: 12,
|
||||||
|
5: 19,
|
||||||
|
6: 28,
|
||||||
|
7: 39,
|
||||||
|
8: 52,
|
||||||
|
9: 67,
|
||||||
|
10: 84,
|
||||||
|
11: 103,
|
||||||
|
12: 124,
|
||||||
|
13: 147,
|
||||||
|
14: 172,
|
||||||
|
15: 199,
|
||||||
|
16: 228,
|
||||||
|
17: 259,
|
||||||
|
18: 292,
|
||||||
|
19: 327,
|
||||||
|
20: 364,
|
||||||
|
21: 364,
|
||||||
|
22: 364,
|
||||||
|
23: 364,
|
||||||
|
24: 364,
|
||||||
|
25: 364,
|
||||||
|
26: 364,
|
||||||
|
27: 364,
|
||||||
|
28: 364,
|
||||||
|
29: 364,
|
||||||
|
30: 364,
|
||||||
|
31: 364,
|
||||||
|
32: 364,
|
||||||
|
33: 364,
|
||||||
|
34: 364,
|
||||||
|
35: 364,
|
||||||
|
36: 364,
|
||||||
|
37: 364,
|
||||||
|
38: 364,
|
||||||
|
39: 364,
|
||||||
|
40: 364,
|
||||||
|
41: 364,
|
||||||
|
42: 364,
|
||||||
|
43: 364,
|
||||||
|
44: 364,
|
||||||
|
45: 364,
|
||||||
|
46: 364,
|
||||||
|
47: 364,
|
||||||
|
48: 364,
|
||||||
|
49: 364,
|
||||||
|
50: 364,
|
||||||
|
}}
|
|
@ -12,7 +12,6 @@ import (
|
||||||
|
|
||||||
type Trial struct {
|
type Trial struct {
|
||||||
Cards map[int]card.Card
|
Cards map[int]card.Card
|
||||||
Lives int
|
|
||||||
|
|
||||||
SelectionState int
|
SelectionState int
|
||||||
PendingSelection [2]int
|
PendingSelection [2]int
|
||||||
|
@ -21,9 +20,8 @@ type Trial struct {
|
||||||
History [][2]int
|
History [][2]int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTrial(lives int) *Trial {
|
func NewTrial() *Trial {
|
||||||
return &Trial{
|
return &Trial{
|
||||||
Lives: lives,
|
|
||||||
Cards: make(map[int]card.Card, 7),
|
Cards: make(map[int]card.Card, 7),
|
||||||
Shown: make(map[int]card.Card, 7),
|
Shown: make(map[int]card.Card, 7),
|
||||||
PendingSelection: [2]int{-1, -1},
|
PendingSelection: [2]int{-1, -1},
|
||||||
|
@ -34,9 +32,6 @@ func (t *Trial) SelectCard(id int) (card.Card, error) {
|
||||||
if id > len(t.Cards) {
|
if id > len(t.Cards) {
|
||||||
return card.Card{}, errs.Invalid("index out of bounds")
|
return card.Card{}, errs.Invalid("index out of bounds")
|
||||||
}
|
}
|
||||||
if t.Lives == 0 {
|
|
||||||
return card.Card{}, errs.Logic("game over")
|
|
||||||
}
|
|
||||||
switch t.SelectionState {
|
switch t.SelectionState {
|
||||||
case 0: // start selection
|
case 0: // start selection
|
||||||
t.SelectionState = 1
|
t.SelectionState = 1
|
||||||
|
@ -51,36 +46,37 @@ func (t *Trial) SelectCard(id int) (card.Card, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Trial) CheckSelection() bool {
|
func (t *Trial) CheckSelection() (points int, lifechange float64) {
|
||||||
switch t.SelectionState {
|
switch t.SelectionState {
|
||||||
case 0, 1:
|
case 0, 1:
|
||||||
return false
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
t.SelectionState = 0
|
t.SelectionState = 0
|
||||||
}()
|
}()
|
||||||
|
lifechange = -1
|
||||||
c1, ok := t.Cards[t.PendingSelection[0]]
|
c1, ok := t.Cards[t.PendingSelection[0]]
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return
|
||||||
}
|
}
|
||||||
c2, ok := t.Cards[t.PendingSelection[1]]
|
c2, ok := t.Cards[t.PendingSelection[1]]
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return
|
||||||
}
|
}
|
||||||
if c1.Id == c2.Id {
|
if c1.Id == c2.Id {
|
||||||
if c1.Name == c2.Name {
|
if c1.Name == c2.Name {
|
||||||
t.Shown[t.PendingSelection[0]] = c1
|
t.Shown[t.PendingSelection[0]] = c1
|
||||||
t.Shown[t.PendingSelection[1]] = c2
|
t.Shown[t.PendingSelection[1]] = c2
|
||||||
return true
|
if c1.BonusLife || c2.BonusLife {
|
||||||
|
return 10, 1
|
||||||
|
}
|
||||||
|
return 10, 0.35
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.History = append(t.History, t.PendingSelection)
|
t.History = append(t.History, t.PendingSelection)
|
||||||
t.PendingSelection = [2]int{-1, -1}
|
t.PendingSelection = [2]int{-1, -1}
|
||||||
t.Lives = t.Lives - 1
|
return 0, -1
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Trial) Show() map[int]card.Card {
|
func (t *Trial) Show() map[int]card.Card {
|
||||||
|
@ -102,8 +98,8 @@ func (t *Trial) ShowString() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
outs := ""
|
outs := ""
|
||||||
for _, k := range t.CardKeys() {
|
for n, k := range t.CardKeys() {
|
||||||
piece := "[???]"
|
piece := fmt.Sprintf("[??%d??]", n+1)
|
||||||
if v, ok := out[k]; ok {
|
if v, ok := out[k]; ok {
|
||||||
piece = fmt.Sprintf("[%s]", v.Name)
|
piece = fmt.Sprintf("[%s]", v.Name)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue