Add initial support for BEI protocol

This commit is contained in:
Trevor Slocum 2023-12-20 16:47:51 -08:00
parent a46a92776b
commit 4e0aeae747
4 changed files with 142 additions and 0 deletions

131
bei.go Normal file
View file

@ -0,0 +1,131 @@
package tabula
import (
"bufio"
"bytes"
"log"
"net"
"strconv"
"code.rocket9labs.com/tslocum/bei"
)
type BEIServer struct {
}
func NewBEIServer() *BEIServer {
return &BEIServer{}
}
func (s *BEIServer) handleConnection(conn net.Conn) {
analysis := make([]*Analysis, 0, AnalysisBufferSize)
var beiCommand bool
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
if scanner.Err() != nil {
log.Printf("error: failed to read from client: %s", scanner.Err())
conn.Close()
return
}
if !beiCommand && !bytes.Equal(scanner.Bytes(), []byte("bei")) {
log.Printf("error: failed to read from client: failed to receive bei command")
conn.Close()
return
}
switch {
case bytes.Equal(scanner.Bytes(), []byte("bei")):
buf, err := bei.EncodeEvent(&bei.EventOkBEI{
Version: 1,
ID: map[string]string{
"name": "tabula",
},
})
if err != nil {
log.Fatalf("error: failed to encode event: %s", err)
}
conn.Write(buf)
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)
if err != nil {
log.Printf("error: failed to read from client: failed to decode state: %s", 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()
return
}
move := &bei.Move{}
for _, m := range analysis[0].Moves {
if m[0] == 0 && m[1] == 0 {
break
}
move.Play = append(move.Play, &bei.Play{From: int(m[0]), To: int(m[1])})
}
buf, err := bei.EncodeEvent(&bei.EventOkMove{
Moves: []*bei.Move{move},
})
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()
return
}
}
if scanner.Err() != nil {
log.Printf("error: failed to read from client: %s", scanner.Err())
conn.Close()
return
}
}
func (s *BEIServer) Listen(address string) {
listener, err := net.Listen("tcp", address)
if err != nil {
log.Fatalf("failed to listen on %s: %s", address, err)
}
log.Printf("Listening for connections on %s...", address)
for {
conn, err := listener.Accept()
if err != nil {
log.Fatalf("failed to listen on %s: %s", address, err)
}
go s.handleConnection(conn)
}
}

View file

@ -10,7 +10,9 @@ import (
)
func main() {
var address string
var pips bool
flag.StringVar(&address, "address", "", "Listen for BEI connections on specified address (TCP)")
flag.BoolVar(&pips, "pips", false, "Print table of pseudopip values")
flag.Parse()
@ -23,6 +25,11 @@ func main() {
return
}
if address != "" {
s := tabula.NewBEIServer()
s.Listen(address)
}
//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}

2
go.mod
View file

@ -1,3 +1,5 @@
module code.rocket9labs.com/tslocum/tabula
go 1.17
require code.rocket9labs.com/tslocum/bei v0.0.0-20231220232111-b1d4144d27bb

2
go.sum
View file

@ -0,0 +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=