Add initial support for BEI protocol
This commit is contained in:
parent
a46a92776b
commit
4e0aeae747
4 changed files with 142 additions and 0 deletions
131
bei.go
Normal file
131
bei.go
Normal 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)
|
||||
}
|
||||
}
|
|
@ -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
2
go.mod
|
@ -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
2
go.sum
|
@ -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=
|
Loading…
Reference in a new issue