Record replays
This commit is contained in:
parent
ac522526e7
commit
5191ecb83d
5 changed files with 73 additions and 27 deletions
27
REPLAY.md
27
REPLAY.md
|
@ -15,40 +15,37 @@ The index table consists of one or more lines in the following format:
|
|||
`bgammon-replay <index>`
|
||||
|
||||
Games are in chronological order.
|
||||
The index specifies the index of the first byte of the first line of a game.
|
||||
The index is always eight digits with leading zeroes.
|
||||
The index specifies the position of the first byte of the first line of a game.
|
||||
The index is always eight digits in length with leading zeroes.
|
||||
|
||||
### Game
|
||||
|
||||
#### Metadata
|
||||
|
||||
The first line of the file specifies the metadata.
|
||||
The first line of the game is the metadata.
|
||||
|
||||
`i <player1> <player2> <total> <score1> <score2> <winner> <points> <acey>`
|
||||
|
||||
#### Index table
|
||||
|
||||
The index table consists of one or more lines in the following format:
|
||||
|
||||
`g <player> <index>`
|
||||
|
||||
The index specifies the index of the first byte of each line corresponding to each turn in the game.
|
||||
The index is always eight digits with leading zeroes.
|
||||
|
||||
#### Events
|
||||
|
||||
The remaining lines of the game are the events.
|
||||
|
||||
Events are in the following format:
|
||||
|
||||
`<player> <event>`
|
||||
|
||||
##### Double
|
||||
|
||||
Accepted:
|
||||
|
||||
`d 2 1`
|
||||
`1 d 2 1`
|
||||
|
||||
Declined:
|
||||
|
||||
`d 2 0`
|
||||
`1 d 2 0`
|
||||
|
||||
##### Roll and move
|
||||
|
||||
Moves are always specified from player 1's perspective.
|
||||
|
||||
`r 5-3 13/8 24/21`
|
||||
`1 r 5-3 13/8 24/21`
|
||||
|
|
|
@ -48,7 +48,8 @@ CREATE TABLE game (
|
|||
account2 integer NOT NULL,
|
||||
points integer NOT NULL,
|
||||
winner integer NOT NULL,
|
||||
wintype integer NOT NULL
|
||||
wintype integer NOT NULL,
|
||||
replay TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
`
|
||||
|
||||
|
@ -387,11 +388,16 @@ func setAccountSetting(id int, name string, value int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func recordGameResult(g *bgammon.Game, winType int, account1 int, account2 int) error {
|
||||
if db == nil || g.Started.IsZero() || g.Ended.IsZero() || g.Winner == 0 {
|
||||
func recordGameResult(g *bgammon.Game, winType int, account1 int, account2 int, replay [][]byte) error {
|
||||
if db == nil || g.Started.IsZero() || g.Winner == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ended := g.Ended
|
||||
if ended.IsZero() {
|
||||
ended = time.Now()
|
||||
}
|
||||
|
||||
tx, err := begin()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -402,7 +408,7 @@ func recordGameResult(g *bgammon.Game, winType int, account1 int, account2 int)
|
|||
if g.Acey {
|
||||
acey = 1
|
||||
}
|
||||
_, err = tx.Exec(context.Background(), "INSERT INTO game (acey, started, ended, player1, account1, player2, account2, points, winner, wintype) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", acey, g.Started.Unix(), g.Ended.Unix(), g.Player1.Name, account1, g.Player2.Name, account2, g.Points, g.Winner, winType)
|
||||
_, err = tx.Exec(context.Background(), "INSERT INTO game (acey, started, ended, player1, account1, player2, account2, points, winner, wintype, replay) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", acey, g.Started.Unix(), ended.Unix(), g.Player1.Name, account1, g.Player2.Name, account2, g.Points, g.Winner, winType, bytes.Join(replay, []byte("\n")))
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ func setAccountSetting(id int, name string, value int) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func recordGameResult(g *bgammon.Game, winType int, account1 int, account2 int) error {
|
||||
func recordGameResult(g *bgammon.Game, winType int, account1 int, account2 int, replay [][]byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,11 @@ import (
|
|||
"code.rocket9labs.com/tslocum/bgammon"
|
||||
)
|
||||
|
||||
type replayEvent struct {
|
||||
Player int
|
||||
Event []byte
|
||||
}
|
||||
|
||||
type serverGame struct {
|
||||
id int
|
||||
created int64
|
||||
|
@ -22,6 +27,7 @@ type serverGame struct {
|
|||
rematch int
|
||||
rejoin1 bool
|
||||
rejoin2 bool
|
||||
replay [][]byte
|
||||
*bgammon.Game
|
||||
}
|
||||
|
||||
|
|
|
@ -992,13 +992,22 @@ COMMANDS:
|
|||
cmd.client.sendNotice("Declined double offer")
|
||||
clientGame.opponent(cmd.client).sendNotice(fmt.Sprintf("%s declined double offer.", cmd.client.name))
|
||||
|
||||
acey := 0
|
||||
if clientGame.Acey {
|
||||
acey = 1
|
||||
}
|
||||
clientGame.replay = append([][]byte{[]byte(fmt.Sprintf("i %s %s %d %d %d %d %d %d", clientGame.Player1.Name, clientGame.Player2.Name, clientGame.Points, clientGame.Player1.Points, clientGame.Player2.Points, clientGame.Winner, clientGame.DoubleValue, acey))}, clientGame.replay...)
|
||||
|
||||
clientGame.replay = append(clientGame.replay, []byte(fmt.Sprintf("%d d %d 0", clientGame.Turn, clientGame.DoubleValue*2)))
|
||||
|
||||
var reset bool
|
||||
if cmd.client.playerNumber == 1 {
|
||||
clientGame.Player2.Points = clientGame.Player2.Points + clientGame.DoubleValue
|
||||
if clientGame.Player2.Points >= clientGame.Points {
|
||||
clientGame.Winner = 2
|
||||
clientGame.Ended = time.Now()
|
||||
} else {
|
||||
clientGame.Reset()
|
||||
reset = true
|
||||
}
|
||||
} else {
|
||||
clientGame.Player1.Points = clientGame.Player2.Points + clientGame.DoubleValue
|
||||
|
@ -1006,7 +1015,7 @@ COMMANDS:
|
|||
clientGame.Winner = 1
|
||||
clientGame.Ended = time.Now()
|
||||
} else {
|
||||
clientGame.Reset()
|
||||
reset = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1021,11 +1030,17 @@ COMMANDS:
|
|||
winEvent.Player = clientGame.Player2.Name
|
||||
}
|
||||
|
||||
err := recordGameResult(clientGame.Game, 4, clientGame.client1.account, clientGame.client2.account)
|
||||
err := recordGameResult(clientGame.Game, 4, clientGame.client1.account, clientGame.client2.account, clientGame.replay)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to record game result: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if reset {
|
||||
clientGame.Reset()
|
||||
clientGame.replay = clientGame.replay[:0]
|
||||
}
|
||||
|
||||
clientGame.eachClient(func(client *serverClient) {
|
||||
clientGame.sendBoard(client)
|
||||
if winEvent != nil {
|
||||
|
@ -1273,14 +1288,23 @@ COMMANDS:
|
|||
}
|
||||
}
|
||||
|
||||
acey := 0
|
||||
if clientGame.Acey {
|
||||
acey = 1
|
||||
}
|
||||
clientGame.replay = append([][]byte{[]byte(fmt.Sprintf("i %s %s %d %d %d %d %d %d", clientGame.Player1.Name, clientGame.Player2.Name, clientGame.Points, clientGame.Player1.Points, clientGame.Player2.Points, clientGame.Winner, winPoints, acey))}, clientGame.replay...)
|
||||
|
||||
clientGame.replay = append(clientGame.replay, []byte(fmt.Sprintf("%d r %d-%d %s", clientGame.Turn, clientGame.Roll1, clientGame.Roll2, bgammon.FormatMoves(clientGame.Moves))))
|
||||
|
||||
winEvent = &bgammon.EventWin{
|
||||
Points: winPoints * clientGame.DoubleValue,
|
||||
}
|
||||
var reset bool
|
||||
if clientGame.Winner == 1 {
|
||||
winEvent.Player = clientGame.Player1.Name
|
||||
clientGame.Player1.Points = clientGame.Player1.Points + winPoints*clientGame.DoubleValue
|
||||
if clientGame.Player1.Points < clientGame.Points {
|
||||
clientGame.Reset()
|
||||
reset = true
|
||||
} else {
|
||||
clientGame.Ended = time.Now()
|
||||
}
|
||||
|
@ -1288,7 +1312,7 @@ COMMANDS:
|
|||
winEvent.Player = clientGame.Player2.Name
|
||||
clientGame.Player2.Points = clientGame.Player2.Points + winPoints*clientGame.DoubleValue
|
||||
if clientGame.Player2.Points < clientGame.Points {
|
||||
clientGame.Reset()
|
||||
reset = true
|
||||
} else {
|
||||
clientGame.Ended = time.Now()
|
||||
}
|
||||
|
@ -1298,10 +1322,15 @@ COMMANDS:
|
|||
if clientGame.Acey {
|
||||
winType = 1
|
||||
}
|
||||
err := recordGameResult(clientGame.Game, winType, clientGame.client1.account, clientGame.client2.account)
|
||||
err := recordGameResult(clientGame.Game, winType, clientGame.client1.account, clientGame.client2.account, clientGame.replay)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to record game result: %s", err)
|
||||
}
|
||||
|
||||
if reset {
|
||||
clientGame.Reset()
|
||||
clientGame.replay = clientGame.replay[:0]
|
||||
}
|
||||
}
|
||||
|
||||
clientGame.eachClient(func(client *serverClient) {
|
||||
|
@ -1378,6 +1407,7 @@ COMMANDS:
|
|||
cmd.client.sendNotice("Accepted double.")
|
||||
opponent.sendNotice(fmt.Sprintf("%s accepted double.", cmd.client.name))
|
||||
|
||||
clientGame.replay = append(clientGame.replay, []byte(fmt.Sprintf("%d d %d 1", clientGame.Turn, clientGame.DoubleValue)))
|
||||
clientGame.eachClient(func(client *serverClient) {
|
||||
clientGame.sendBoard(client)
|
||||
})
|
||||
|
@ -1405,6 +1435,10 @@ COMMANDS:
|
|||
continue
|
||||
}
|
||||
|
||||
recordEvent := func() {
|
||||
clientGame.replay = append(clientGame.replay, []byte(fmt.Sprintf("%d r %d-%d %s", clientGame.Turn, clientGame.Roll1, clientGame.Roll2, bgammon.FormatMoves(clientGame.Moves))))
|
||||
}
|
||||
|
||||
if clientGame.Acey && ((clientGame.Roll1 == 1 && clientGame.Roll2 == 2) || (clientGame.Roll1 == 2 && clientGame.Roll2 == 1)) && len(clientGame.Moves) == 2 {
|
||||
var doubles int
|
||||
if len(params) > 0 {
|
||||
|
@ -1417,6 +1451,7 @@ COMMANDS:
|
|||
continue
|
||||
}
|
||||
|
||||
recordEvent()
|
||||
clientGame.NextTurn(true)
|
||||
clientGame.Roll1, clientGame.Roll2 = doubles, doubles
|
||||
clientGame.Reroll = true
|
||||
|
@ -1431,6 +1466,7 @@ COMMANDS:
|
|||
client.sendEvent(ev)
|
||||
})
|
||||
} else if clientGame.Acey && clientGame.Reroll {
|
||||
recordEvent()
|
||||
clientGame.NextTurn(true)
|
||||
clientGame.Roll1, clientGame.Roll2 = 0, 0
|
||||
if !clientGame.roll(cmd.client.playerNumber) {
|
||||
|
@ -1450,6 +1486,7 @@ COMMANDS:
|
|||
clientGame.sendBoard(client)
|
||||
})
|
||||
} else {
|
||||
recordEvent()
|
||||
clientGame.NextTurn(false)
|
||||
if clientGame.Winner == 0 {
|
||||
gameState := &bgammon.GameState{
|
||||
|
@ -1629,7 +1666,7 @@ COMMANDS:
|
|||
clientGame.Turn = 2
|
||||
clientGame.Roll1 = 4
|
||||
clientGame.Roll2 = 4
|
||||
clientGame.Board = []int{1, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, -1, 1, -1}
|
||||
clientGame.Board = []int{1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -1, 0, 0}
|
||||
|
||||
clientGame.eachClient(func(client *serverClient) {
|
||||
clientGame.sendBoard(client)
|
||||
|
|
Loading…
Reference in a new issue