Support playing acey-deucey games
This commit is contained in:
parent
612426a93d
commit
44ad618f32
4 changed files with 63 additions and 27 deletions
|
@ -36,11 +36,13 @@ type Client struct {
|
|||
sentGreeting bool
|
||||
rolled bool
|
||||
lastActivity time.Time
|
||||
acey bool
|
||||
quiet bool
|
||||
thinkTime time.Duration
|
||||
analysis []*tabula.Analysis
|
||||
}
|
||||
|
||||
func NewClient(address string, username string, password string, points int, quiet bool, thinkTime time.Duration) *Client {
|
||||
func NewClient(address string, username string, password string, points int, acey bool, quiet bool, thinkTime time.Duration) *Client {
|
||||
const bufferSize = 10
|
||||
c := &Client{
|
||||
Address: address,
|
||||
|
@ -49,15 +51,17 @@ func NewClient(address string, username string, password string, points int, qui
|
|||
Events: make(chan interface{}, bufferSize),
|
||||
Out: make(chan []byte, bufferSize),
|
||||
points: points,
|
||||
acey: acey,
|
||||
quiet: quiet,
|
||||
thinkTime: thinkTime,
|
||||
analysis: make([]*tabula.Analysis, 0, tabula.AnalysisBufferSize),
|
||||
}
|
||||
go c.handleTimeout()
|
||||
return c
|
||||
}
|
||||
|
||||
func NewLocalClient(conn net.Conn, address string, username string, password string, points int, quiet bool, thinkTime time.Duration) {
|
||||
c := NewClient(address, username, password, points, quiet, thinkTime)
|
||||
func NewLocalClient(conn net.Conn, address string, username string, password string, points int, acey bool, quiet bool, thinkTime time.Duration) {
|
||||
c := NewClient(address, username, password, points, acey, quiet, thinkTime)
|
||||
c.connecting = true
|
||||
go c.connectTCP(conn)
|
||||
c.HandleEvents()
|
||||
|
@ -279,7 +283,11 @@ func (c *Client) handleTCPRead(conn net.Conn) {
|
|||
}
|
||||
|
||||
func (c *Client) createMatch() {
|
||||
c.Out <- []byte(fmt.Sprintf("c public %d", c.points))
|
||||
acey := 0
|
||||
if c.acey {
|
||||
acey = 1
|
||||
}
|
||||
c.Out <- []byte(fmt.Sprintf("c public %d %d", c.points, acey))
|
||||
c.sentGreeting = false
|
||||
c.rolled = false
|
||||
}
|
||||
|
@ -407,31 +415,25 @@ func (c *Client) HandleEvents() {
|
|||
continue
|
||||
}
|
||||
|
||||
b := Game.Board
|
||||
var roll1, roll2, roll3, roll4 int8
|
||||
roll1, roll2 = int8(Game.Roll1), int8(Game.Roll2)
|
||||
if roll1 == roll2 {
|
||||
roll3, roll4 = int8(Game.Roll1), int8(Game.Roll2)
|
||||
}
|
||||
boardState := tabula.Board{int8(b[0]), int8(b[1]), int8(b[2]), int8(b[3]), int8(b[4]), int8(b[5]), int8(b[6]), int8(b[7]), int8(b[8]), int8(b[9]), int8(b[10]), int8(b[11]), int8(b[12]), int8(b[13]), int8(b[14]), int8(b[15]), int8(b[16]), int8(b[17]), int8(b[18]), int8(b[19]), int8(b[20]), int8(b[21]), int8(b[22]), int8(b[23]), int8(b[24]), int8(b[25]), int8(b[26]), int8(b[27]), roll1, roll2, roll3, roll4}
|
||||
|
||||
var t time.Time
|
||||
if c.thinkTime != 0 {
|
||||
t = time.Now()
|
||||
}
|
||||
|
||||
boardState := tabulaBoard(Game.Board)
|
||||
|
||||
available, _ := boardState.Available(1)
|
||||
result := boardState.Analyze(available)
|
||||
if len(result) == 0 {
|
||||
boardState.Analyze(available, &c.analysis)
|
||||
if len(c.analysis) == 0 {
|
||||
log.Printf("Legal moves: %+v", Game.Available)
|
||||
log.Fatalf("NO PLAYABLE MOVES RETURNED: %+v", result)
|
||||
log.Fatalf("NO PLAYABLE MOVES RETURNED: %+v", c.analysis)
|
||||
}
|
||||
|
||||
if !c.quiet {
|
||||
log.Println("==========")
|
||||
log.Println("Legal moves:", Game.Available)
|
||||
|
||||
log.Println("Past:", result[0].Past)
|
||||
log.Println("Past:", c.analysis[0].Past)
|
||||
|
||||
builder := &strings.Builder{}
|
||||
builder.Write([]byte("Board: "))
|
||||
|
@ -446,15 +448,17 @@ func (c *Client) HandleEvents() {
|
|||
const padding = 3
|
||||
w := tabwriter.NewWriter(os.Stderr, 0, 0, padding, ' ', 0)
|
||||
fmt.Fprintln(w, "Moves\tScore\tPlayer Score\tPips\tBlots\tHits\tOpponent Score\tPips\tBlots\tHits\t")
|
||||
for _, r := range result {
|
||||
for _, r := range c.analysis {
|
||||
fmt.Fprintf(w, "%s\t%.2f\t%.2f\t%d\t%d\t%d\t%.2f\t%.2f\t%.2f\t%.2f\t\n", fmt.Sprint(r.Moves), r.Score, r.PlayerScore, r.Pips, r.Blots, r.Hits, r.OppScore, r.OppPips, r.OppBlots, r.OppHits)
|
||||
}
|
||||
w.Flush()
|
||||
log.Println("==========")
|
||||
}
|
||||
|
||||
for _, move := range result[0].Moves {
|
||||
if move[0] == 0 || move[0] == 25 {
|
||||
for _, move := range c.analysis[0].Moves {
|
||||
if move[0] == 0 {
|
||||
c.Out <- []byte(fmt.Sprintf("mv off/%d", move[1]))
|
||||
} else if move[0] == 25 {
|
||||
c.Out <- []byte(fmt.Sprintf("mv bar/%d", move[1]))
|
||||
} else {
|
||||
c.Out <- []byte(fmt.Sprintf("mv %d/%d", move[0], move[1]))
|
||||
|
@ -467,7 +471,17 @@ func (c *Client) HandleEvents() {
|
|||
time.Sleep(c.thinkTime - s)
|
||||
}
|
||||
}
|
||||
c.Out <- []byte("ok")
|
||||
if Game.MayChooseRoll() {
|
||||
newGame := Game.Copy()
|
||||
for _, move := range c.analysis[0].Moves {
|
||||
newGame.AddLocalMove(move)
|
||||
}
|
||||
newBoardState := tabulaBoard(newGame.Board)
|
||||
doubles := newBoardState.ChooseDoubles(&c.analysis)
|
||||
c.Out <- []byte(fmt.Sprintf("ok %d", doubles))
|
||||
} else {
|
||||
c.Out <- []byte("ok")
|
||||
}
|
||||
c.lastActivity = time.Now()
|
||||
case *bgammon.EventRolled:
|
||||
Game.Roll1 = ev.Roll1
|
||||
|
@ -518,3 +532,23 @@ func (c *Client) HandleEvents() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func tabulaBoard(b []int) tabula.Board {
|
||||
var roll1, roll2, roll3, roll4 int8
|
||||
roll1, roll2 = int8(Game.Roll1), int8(Game.Roll2)
|
||||
if roll1 == roll2 {
|
||||
roll3, roll4 = int8(Game.Roll1), int8(Game.Roll2)
|
||||
}
|
||||
entered1, entered2 := int8(1), int8(1)
|
||||
acey := int8(0)
|
||||
if Game.Acey {
|
||||
if !Game.Player1.Entered {
|
||||
entered1 = 0
|
||||
}
|
||||
if !Game.Player2.Entered {
|
||||
entered2 = 0
|
||||
}
|
||||
acey = 1
|
||||
}
|
||||
return tabula.Board{int8(b[0]), int8(b[1]), int8(b[2]), int8(b[3]), int8(b[4]), int8(b[5]), int8(b[6]), int8(b[7]), int8(b[8]), int8(b[9]), int8(b[10]), int8(b[11]), int8(b[12]), int8(b[13]), int8(b[14]), int8(b[15]), int8(b[16]), int8(b[17]), int8(b[18]), int8(b[19]), int8(b[20]), int8(b[21]), int8(b[22]), int8(b[23]), int8(b[24]), int8(b[25]), int8(b[26]), int8(b[27]), roll1, roll2, roll3, roll4, entered1, entered2, acey}
|
||||
}
|
||||
|
|
4
go.mod
4
go.mod
|
@ -3,7 +3,7 @@ module code.rocket9labs.com/tslocum/bgammon-tabula-bot
|
|||
go 1.17
|
||||
|
||||
require (
|
||||
code.rocket9labs.com/tslocum/bgammon v0.0.0-20231208220405-8c4b5112ba77
|
||||
code.rocket9labs.com/tslocum/tabula v0.0.0-20231209094435-959d43321c78
|
||||
code.rocket9labs.com/tslocum/bgammon v0.0.0-20231211185248-f939d053a819
|
||||
code.rocket9labs.com/tslocum/tabula v0.0.0-20231212190831-bfc39a406f20
|
||||
nhooyr.io/websocket v1.8.10
|
||||
)
|
||||
|
|
8
go.sum
8
go.sum
|
@ -1,6 +1,6 @@
|
|||
code.rocket9labs.com/tslocum/bgammon v0.0.0-20231208220405-8c4b5112ba77 h1:MnAW9Icj5mDOaFnyT3BcH/xRoa0stZEJjs+hQg0lyj0=
|
||||
code.rocket9labs.com/tslocum/bgammon v0.0.0-20231208220405-8c4b5112ba77/go.mod h1:u3nbSwxWnwOXbCNPQD4s3abGTfvA4/gi9U626f7ZN9Q=
|
||||
code.rocket9labs.com/tslocum/tabula v0.0.0-20231209094435-959d43321c78 h1:5E+Av3zTjMndkoz9n7QSl0icA1eBjnzFXtpbVADhXy8=
|
||||
code.rocket9labs.com/tslocum/tabula v0.0.0-20231209094435-959d43321c78/go.mod h1:XtS6M8qcK0fnUn4k5I7h4JcZ2sz2WEAXOcF2DLaQBME=
|
||||
code.rocket9labs.com/tslocum/bgammon v0.0.0-20231211185248-f939d053a819 h1:QUps5Kz32BpKMvVISbRZe2gtr1BYqfPOSV1UifpHADU=
|
||||
code.rocket9labs.com/tslocum/bgammon v0.0.0-20231211185248-f939d053a819/go.mod h1:u3nbSwxWnwOXbCNPQD4s3abGTfvA4/gi9U626f7ZN9Q=
|
||||
code.rocket9labs.com/tslocum/tabula v0.0.0-20231212190831-bfc39a406f20 h1:Y/OwzfDQcm6FLCMKa8eMI+MjpcVDgmnHwsewd22KbHo=
|
||||
code.rocket9labs.com/tslocum/tabula v0.0.0-20231212190831-bfc39a406f20/go.mod h1:XtS6M8qcK0fnUn4k5I7h4JcZ2sz2WEAXOcF2DLaQBME=
|
||||
nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q=
|
||||
nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
|
||||
|
|
4
main.go
4
main.go
|
@ -18,6 +18,7 @@ func main() {
|
|||
username string
|
||||
password string
|
||||
points int
|
||||
acey bool
|
||||
quiet bool
|
||||
thinkTime time.Duration
|
||||
debug int
|
||||
|
@ -26,6 +27,7 @@ func main() {
|
|||
flag.StringVar(&username, "username", "", "Username")
|
||||
flag.StringVar(&password, "password", "", "Password")
|
||||
flag.IntVar(&points, "points", 1, "Match points")
|
||||
flag.BoolVar(&acey, "acey", false, "Create acey-deucey match")
|
||||
flag.Float64Var(&tabula.WeightBlot, "weight-blot", tabula.WeightBlot, "Weight (multiplier) when scoring blots")
|
||||
flag.Float64Var(&tabula.WeightHit, "weight-hit", tabula.WeightHit, "Weight (multiplier) when scoring hits")
|
||||
flag.Float64Var(&tabula.WeightOppScore, "weight-score", tabula.WeightOppScore, "Weight (multiplier) when adding opponent score to overall score")
|
||||
|
@ -40,7 +42,7 @@ func main() {
|
|||
}()
|
||||
}
|
||||
|
||||
c := bot.NewClient(serverAddress, username, password, points, quiet, thinkTime)
|
||||
c := bot.NewClient(serverAddress, username, password, points, acey, quiet, thinkTime)
|
||||
|
||||
go c.Connect()
|
||||
c.HandleEvents()
|
||||
|
|
Loading…
Reference in a new issue