Support playing acey-deucey games via BEI
This commit is contained in:
parent
4e0aeae747
commit
f11e319116
5 changed files with 172 additions and 76 deletions
97
bei.go
97
bei.go
|
@ -3,6 +3,7 @@ package tabula
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"strconv"
|
||||
|
@ -47,38 +48,15 @@ func (s *BEIServer) handleConnection(conn net.Conn) {
|
|||
conn.Write([]byte("\n"))
|
||||
beiCommand = true
|
||||
case bytes.HasPrefix(scanner.Bytes(), []byte("move ")):
|
||||
var stateInts []int
|
||||
for _, v := range bytes.Split(scanner.Bytes()[5:], []byte(",")) {
|
||||
i, err := strconv.Atoi(string(v))
|
||||
if err != nil {
|
||||
log.Printf("error: failed to read from client: failed to decode state: %s", err)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
stateInts = append(stateInts, i)
|
||||
}
|
||||
state, err := bei.DecodeState(stateInts)
|
||||
b, err := parseState(scanner.Bytes()[5:])
|
||||
if err != nil {
|
||||
log.Printf("error: failed to read from client: failed to decode state: %s", err)
|
||||
log.Println(err)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
b := Board{}
|
||||
for i, v := range state.Board {
|
||||
b[i] = int8(v)
|
||||
}
|
||||
b[SpaceRoll1] = int8(state.Roll1)
|
||||
b[SpaceRoll2] = int8(state.Roll2)
|
||||
if state.Roll1 == state.Roll2 {
|
||||
b[SpaceRoll3], b[SpaceRoll4] = int8(state.Roll1), int8(state.Roll2)
|
||||
}
|
||||
// TODO entered, acey
|
||||
b[SpaceEnteredPlayer] = 1
|
||||
b[SpaceEnteredOpponent] = 1
|
||||
|
||||
available, _ := b.Available(1)
|
||||
b.Analyze(available, &analysis)
|
||||
|
||||
if len(analysis) == 0 {
|
||||
log.Printf("error: failed to read from client: zero moves returned for analysis")
|
||||
conn.Close()
|
||||
|
@ -100,6 +78,39 @@ func (s *BEIServer) handleConnection(conn net.Conn) {
|
|||
}
|
||||
conn.Write(buf)
|
||||
conn.Write([]byte("\n"))
|
||||
case bytes.HasPrefix(scanner.Bytes(), []byte("choose ")):
|
||||
b, err := parseState(scanner.Bytes()[7:])
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
if b[SpaceAcey] != 1 {
|
||||
log.Println("error: failed to choose roll: state does not represent acey-deucey game")
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
roll := b.ChooseDoubles(&analysis)
|
||||
if roll < 1 || roll > 6 {
|
||||
log.Printf("error: failed to read from client: invalid roll: %d", roll)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
buf, err := bei.EncodeEvent(&bei.EventOkChoose{
|
||||
Rolls: []*bei.ChooseRoll{
|
||||
{
|
||||
Roll: roll,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("error: failed to encode event: %s", err)
|
||||
}
|
||||
conn.Write(buf)
|
||||
conn.Write([]byte("\n"))
|
||||
default:
|
||||
log.Printf("error: received unexpected command from client: %s", scanner.Bytes())
|
||||
conn.Close()
|
||||
|
@ -129,3 +140,39 @@ func (s *BEIServer) Listen(address string) {
|
|||
go s.handleConnection(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func parseState(buf []byte) (Board, error) {
|
||||
var stateInts []int
|
||||
for _, v := range bytes.Split(buf, []byte(",")) {
|
||||
i, err := strconv.Atoi(string(v))
|
||||
if err != nil {
|
||||
return Board{}, fmt.Errorf("error: failed to read from client: failed to decode state: %s", err)
|
||||
}
|
||||
stateInts = append(stateInts, i)
|
||||
}
|
||||
state, err := bei.DecodeState(stateInts)
|
||||
if err != nil {
|
||||
return Board{}, fmt.Errorf("error: failed to read from client: failed to decode state: %s", err)
|
||||
}
|
||||
b := Board{}
|
||||
for i, v := range state.Board {
|
||||
b[i] = int8(v)
|
||||
}
|
||||
b[SpaceRoll1] = int8(state.Roll1)
|
||||
b[SpaceRoll2] = int8(state.Roll2)
|
||||
if state.Roll1 == state.Roll2 {
|
||||
b[SpaceRoll3], b[SpaceRoll4] = int8(state.Roll1), int8(state.Roll2)
|
||||
}
|
||||
b[SpaceEnteredPlayer] = 1
|
||||
b[SpaceEnteredOpponent] = 1
|
||||
if state.Acey {
|
||||
b[SpaceAcey] = 1
|
||||
if !state.Entered1 {
|
||||
b[SpaceEnteredPlayer] = 0
|
||||
}
|
||||
if !state.Entered2 {
|
||||
b[SpaceEnteredOpponent] = 0
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
|
83
board.go
83
board.go
|
@ -543,11 +543,94 @@ func (b Board) Analyze(available [][4][2]int8, result *[]*Analysis) {
|
|||
}
|
||||
}
|
||||
|
||||
if b.StartingPosition(1) && b[SpaceRoll1] != b[SpaceRoll2] {
|
||||
r1, r2 := b[SpaceRoll1], b[SpaceRoll2]
|
||||
if r2 > r1 {
|
||||
r1, r2 = r2, r1
|
||||
}
|
||||
var opening [4][2]int8
|
||||
if r1 == r2 {
|
||||
switch r1 {
|
||||
case 1:
|
||||
opening = [4][2]int8{{24, 23}, {24, 23}, {6, 5}, {6, 5}}
|
||||
case 2:
|
||||
opening = [4][2]int8{{13, 11}, {13, 11}, {11, 9}, {11, 9}}
|
||||
case 3:
|
||||
opening = [4][2]int8{{13, 10}, {13, 10}, {10, 7}, {10, 7}}
|
||||
case 4:
|
||||
opening = [4][2]int8{{13, 9}, {13, 9}, {6, 2}, {6, 2}}
|
||||
case 5:
|
||||
opening = [4][2]int8{{13, 8}, {13, 8}, {8, 3}, {8, 3}}
|
||||
case 6:
|
||||
opening = [4][2]int8{{24, 18}, {24, 18}, {13, 7}, {13, 7}}
|
||||
}
|
||||
} else {
|
||||
switch r1 {
|
||||
case 2:
|
||||
opening = [4][2]int8{{13, 11}, {6, 5}}
|
||||
case 3:
|
||||
switch r2 {
|
||||
case 1:
|
||||
opening = [4][2]int8{{8, 5}, {6, 5}}
|
||||
case 2:
|
||||
opening = [4][2]int8{{13, 11}, {13, 10}}
|
||||
}
|
||||
case 4:
|
||||
switch r2 {
|
||||
case 1:
|
||||
opening = [4][2]int8{{24, 23}, {13, 9}}
|
||||
case 2:
|
||||
opening = [4][2]int8{{8, 4}, {6, 4}}
|
||||
case 3:
|
||||
opening = [4][2]int8{{13, 10}, {13, 9}}
|
||||
}
|
||||
case 5:
|
||||
switch r2 {
|
||||
case 1:
|
||||
opening = [4][2]int8{{24, 23}, {13, 8}}
|
||||
case 2:
|
||||
opening = [4][2]int8{{24, 22}, {13, 8}}
|
||||
case 3:
|
||||
opening = [4][2]int8{{8, 3}, {6, 3}}
|
||||
case 4:
|
||||
opening = [4][2]int8{{24, 20}, {13, 8}}
|
||||
}
|
||||
case 6:
|
||||
switch r2 {
|
||||
case 1:
|
||||
opening = [4][2]int8{{13, 7}, {8, 7}}
|
||||
case 2:
|
||||
opening = [4][2]int8{{24, 18}, {13, 11}}
|
||||
case 3:
|
||||
opening = [4][2]int8{{24, 18}, {13, 10}}
|
||||
case 4:
|
||||
opening = [4][2]int8{{8, 2}, {6, 2}}
|
||||
case 5:
|
||||
opening = [4][2]int8{{24, 18}, {18, 13}}
|
||||
}
|
||||
}
|
||||
}
|
||||
const priorityScore = -1000000
|
||||
for _, a := range *result {
|
||||
if movesEqual(a.Moves, opening) {
|
||||
a.Score = priorityScore
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(*result, func(i, j int) bool {
|
||||
return (*result)[i].Score < (*result)[j].Score
|
||||
})
|
||||
}
|
||||
|
||||
func (b Board) StartingPosition(player int) bool {
|
||||
if player == 1 {
|
||||
return b[6] == 5 && b[8] == 3 && b[13] == 5 && b[24] == 2
|
||||
}
|
||||
return b[1] == -2 && b[12] == -5 && b[17] == -3 && b[19] == -5
|
||||
}
|
||||
|
||||
func (b Board) ChooseDoubles(result *[]*Analysis) int {
|
||||
if b[SpaceAcey] == 0 {
|
||||
return 0
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"code.rocket9labs.com/tslocum/tabula"
|
||||
)
|
||||
|
@ -32,54 +31,21 @@ func main() {
|
|||
|
||||
//b := tabula.Board{0, 0, 0, 0, 0, -1, 8, 0, 4, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, -1, 1, -2, -2, -3, -2, 0, 2, 0, 0, 0, 0, 4, 1, 1, 0}
|
||||
|
||||
b := tabula.Board{0, 0, -2, -2, -2, 4, 0, -1, 0, 0, -2, 4, 0, -2, -1, 0, -2, 4, 0, 2, 0, 0, 0, 0, -1, 0, 1, 0, 4, 1, 0, 0, 1, 1, 1}
|
||||
//b := tabula.Board{0, 0, -2, -2, -2, 4, 0, -1, 0, 0, -2, 4, 0, -2, -1, 0, -2, 4, 0, 2, 0, 0, 0, 0, -1, 0, 1, 0, 4, 1, 0, 0, 1, 1, 1}
|
||||
|
||||
t := time.Now()
|
||||
available, _ := b.Available(1)
|
||||
|
||||
//log.Println(b.Move(15, 19, 2))
|
||||
//log.Println(b.Move(15, 19, 2).UseRoll(15, 19, 2))
|
||||
|
||||
log.Println(available)
|
||||
//os.Exit(0)
|
||||
t2 := time.Now()
|
||||
analysis := make([]*tabula.Analysis, 0, tabula.AnalysisBufferSize)
|
||||
b.Analyze(available, &analysis)
|
||||
t3 := time.Now()
|
||||
|
||||
log.Println("AVAILABLE TOOK ", t2.Sub(t))
|
||||
log.Println("ANALYSIS TOOK ", t3.Sub(t2))
|
||||
|
||||
log.Println("AVAILABLE", available)
|
||||
for i, a := range analysis {
|
||||
log.Printf("%+v %+v", i, a)
|
||||
for r1 := 1; r1 <= 6; r1++ {
|
||||
for r2 := 1; r2 <= 6; r2++ {
|
||||
b := tabula.NewBoard(false)
|
||||
b[tabula.SpaceRoll1] = int8(r1)
|
||||
b[tabula.SpaceRoll2] = int8(r2)
|
||||
if r1 == r2 {
|
||||
b[tabula.SpaceRoll3] = int8(r1)
|
||||
b[tabula.SpaceRoll4] = int8(r2)
|
||||
}
|
||||
available, _ := b.Available(1)
|
||||
b.Analyze(available, &analysis)
|
||||
log.Println("ROLL", r1, r2, analysis[0].Moves)
|
||||
}
|
||||
}
|
||||
|
||||
//t4 := time.Now()
|
||||
//_ = b.ChooseDoubles(&analysis)
|
||||
//log.Println("CHOOSE DOUBLES TOOK ", time.Since(t4))
|
||||
|
||||
/*
|
||||
|
||||
b := tabula.NewBoard(true)
|
||||
b[tabula.SpaceRoll1] = 6
|
||||
b[tabula.SpaceRoll2] = 6
|
||||
b[tabula.SpaceRoll3] = 6
|
||||
b[tabula.SpaceRoll4] = 6
|
||||
b.Print()
|
||||
|
||||
t := time.Now()
|
||||
available, _ := b.Available(1)
|
||||
t2 := time.Now()
|
||||
analysis := make([]*tabula.Analysis, 0, tabula.AnalysisBufferSize)
|
||||
b.Analyze(available, &analysis)
|
||||
t3 := time.Now()
|
||||
|
||||
log.Println("AVAILABLE TOOK ", t2.Sub(t))
|
||||
log.Println("ANALYSIS TOOK ", t3.Sub(t2))
|
||||
|
||||
log.Println("AVAILABLE", available)
|
||||
for i, a := range analysis {
|
||||
log.Printf("%+v %+v", i, a)
|
||||
}*/
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -2,4 +2,4 @@ module code.rocket9labs.com/tslocum/tabula
|
|||
|
||||
go 1.17
|
||||
|
||||
require code.rocket9labs.com/tslocum/bei v0.0.0-20231220232111-b1d4144d27bb
|
||||
require code.rocket9labs.com/tslocum/bei v0.0.0-20231222205835-c070d7c7d5f8
|
||||
|
|
4
go.sum
4
go.sum
|
@ -1,2 +1,2 @@
|
|||
code.rocket9labs.com/tslocum/bei v0.0.0-20231220232111-b1d4144d27bb h1:gU9+YXaDNq/7OyHJ4Mqu5qAyJFAxmCY++Ptk5T/B7w4=
|
||||
code.rocket9labs.com/tslocum/bei v0.0.0-20231220232111-b1d4144d27bb/go.mod h1:tS60/VNAJphKvDBkSLQhKALa15msIAuWWfEKNc4oFZc=
|
||||
code.rocket9labs.com/tslocum/bei v0.0.0-20231222205835-c070d7c7d5f8 h1:QefJxcMg2aneCZuoHPpnDOTsing1mehImilbyyT3SwU=
|
||||
code.rocket9labs.com/tslocum/bei v0.0.0-20231222205835-c070d7c7d5f8/go.mod h1:tS60/VNAJphKvDBkSLQhKALa15msIAuWWfEKNc4oFZc=
|
||||
|
|
Loading…
Reference in a new issue