Add rematch command
This commit is contained in:
parent
d735899304
commit
2a1ae33131
4 changed files with 76 additions and 16 deletions
28
PROTOCOL.md
28
PROTOCOL.md
|
@ -16,58 +16,62 @@ All commands and events are separated by newlines.
|
|||
- Log in to bgammon. A random username is assigned when none is provided.
|
||||
- This must be the first command sent when a client connects to bgammon.
|
||||
- Usernames must contain at least one non-numeric character.
|
||||
- *Aliases:* `l`
|
||||
- Aliases: `l`
|
||||
|
||||
- `loginjson [username] [password]`
|
||||
- Log in to bgammon and enable JSON formatted responses.
|
||||
- All client applications should use the `loginjson` command to log in, as JSON
|
||||
formatted responses are more easily parsed by computers.
|
||||
- *Aliases:* `lj`
|
||||
- Aliases: `lj`
|
||||
|
||||
- `json <on/off>`
|
||||
- Turn JSON formatted messages on or off. JSON messages are not sent by default.
|
||||
|
||||
- `help [command]`
|
||||
- Request help for all commands, or optionally a specific command.
|
||||
- *Aliases:* `h`
|
||||
- Aliases: `h`
|
||||
|
||||
- `list`
|
||||
- List all games.
|
||||
- *Aliases:* `ls`
|
||||
- Aliases: `ls`
|
||||
|
||||
- `create <public/private> [password]`
|
||||
- List all games.
|
||||
- *Aliases:* `c`
|
||||
- Aliases: `c`
|
||||
|
||||
- `join <id>/<username> [password]`
|
||||
- Join game by game ID or by player.
|
||||
- *Aliases:* `j`
|
||||
- Aliases: `j`
|
||||
|
||||
- `roll`
|
||||
- Roll dice.
|
||||
- *Aliases:* `r`
|
||||
- Aliases: `r`
|
||||
|
||||
- `move <from-to> [from-to]...`
|
||||
- Move checkers.
|
||||
- *Aliases:* `m`, `mv`
|
||||
- Aliases: `m`, `mv`
|
||||
|
||||
- `reset`
|
||||
- Reset pending checker movement.
|
||||
- *Aliases:* `r`
|
||||
- Aliases: `r`
|
||||
|
||||
- `ok`
|
||||
- Confirm checker movement and pass turn to next player.
|
||||
- *Aliases:* `k`
|
||||
- Aliases: `k`
|
||||
|
||||
- `rematch`
|
||||
- Request (or accept) a rematch after a match has been finished.
|
||||
- Aliases: `rm`
|
||||
|
||||
- `say <message>`
|
||||
- Send a chat message.
|
||||
- This command can only be used after creating or joining a game.
|
||||
- *Aliases:* `s`
|
||||
- Aliases: `s`
|
||||
|
||||
- `board`
|
||||
- Print current game state in human-readable form.
|
||||
- This command is not normally used, as the game state is provided in JSON format.
|
||||
- *Aliases:* `b`
|
||||
- Aliases: `b`
|
||||
|
||||
- `pong <message>`
|
||||
- Sent in response to server `ping` event to prevent the connection from timing out.
|
||||
|
|
|
@ -19,6 +19,7 @@ type serverGame struct {
|
|||
client2 *serverClient
|
||||
r *rand.Rand
|
||||
allowedPlayers [][]byte // Only matching player names are allowed to join.
|
||||
rematch int
|
||||
*bgammon.Game
|
||||
}
|
||||
|
||||
|
|
|
@ -224,9 +224,6 @@ func (s *server) sendHello(c *serverClient) {
|
|||
c.Write([]byte("hello Welcome to bgammon.org! Please log in by sending the 'login' command. You may specify a username, otherwise you will be assigned a random username. If you specify a username, you may also specify a password. Have fun!"))
|
||||
}
|
||||
|
||||
func (s *server) sendWelcome(c *serverClient) {
|
||||
}
|
||||
|
||||
func (s *server) gameByClient(c *serverClient) *serverGame {
|
||||
s.gamesLock.RLock()
|
||||
defer s.gamesLock.RUnlock()
|
||||
|
@ -703,6 +700,60 @@ COMMANDS:
|
|||
clientGame.eachClient(func(client *serverClient) {
|
||||
clientGame.sendBoard(client)
|
||||
})
|
||||
case bgammon.CommandRematch, "rm":
|
||||
if clientGame == nil {
|
||||
cmd.client.sendNotice("You are not currently in a game.")
|
||||
continue
|
||||
} else if clientGame.Winner == 0 {
|
||||
cmd.client.sendNotice("The game you are in is still in progress.")
|
||||
continue
|
||||
} else if clientGame.rematch == cmd.client.playerNumber {
|
||||
cmd.client.sendNotice("You have already requested a rematch.")
|
||||
continue
|
||||
} else if clientGame.client1 == nil || clientGame.client2 == nil {
|
||||
cmd.client.sendNotice("Your opponent left the game.")
|
||||
continue
|
||||
} else if clientGame.rematch != 0 && clientGame.rematch != cmd.client.playerNumber {
|
||||
s.gamesLock.Lock()
|
||||
|
||||
newGame := newServerGame(<-s.newGameIDs)
|
||||
newGame.name = clientGame.name
|
||||
newGame.password = clientGame.password
|
||||
newGame.client1 = clientGame.client1
|
||||
newGame.client2 = clientGame.client2
|
||||
newGame.Player1 = clientGame.Player1
|
||||
newGame.Player2 = clientGame.Player2
|
||||
s.games = append(s.games, newGame)
|
||||
|
||||
clientGame.client1 = nil
|
||||
clientGame.client2 = nil
|
||||
|
||||
s.gamesLock.Unlock()
|
||||
|
||||
ev1 := &bgammon.EventJoined{
|
||||
GameID: newGame.id,
|
||||
PlayerNumber: 1,
|
||||
}
|
||||
ev1.Player = newGame.Player1.Name
|
||||
|
||||
ev2 := &bgammon.EventJoined{
|
||||
GameID: newGame.id,
|
||||
PlayerNumber: 2,
|
||||
}
|
||||
ev2.Player = newGame.Player2.Name
|
||||
|
||||
newGame.eachClient(func(client *serverClient) {
|
||||
client.sendEvent(ev1)
|
||||
client.sendEvent(ev2)
|
||||
newGame.sendBoard(client)
|
||||
})
|
||||
} else {
|
||||
clientGame.rematch = cmd.client.playerNumber
|
||||
|
||||
clientGame.opponent(cmd.client).sendNotice("Your opponent would like to play again. Type /rematch to accept.")
|
||||
cmd.client.sendNotice("Rematch offer sent.")
|
||||
continue
|
||||
}
|
||||
case bgammon.CommandBoard, "b":
|
||||
if clientGame == nil {
|
||||
cmd.client.sendNotice("You are not currently in a game.")
|
||||
|
@ -725,7 +776,10 @@ COMMANDS:
|
|||
continue
|
||||
}
|
||||
|
||||
clientGame.Board = []int{0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0}
|
||||
clientGame.Turn = 1
|
||||
clientGame.Roll1 = 1
|
||||
clientGame.Roll2 = 2
|
||||
clientGame.Board = []int{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0}
|
||||
|
||||
clientGame.eachClient(func(client *serverClient) {
|
||||
clientGame.sendBoard(client)
|
||||
|
|
|
@ -18,6 +18,7 @@ const (
|
|||
CommandMove = "move" // Move checkers.
|
||||
CommandReset = "reset" // Reset checker movement.
|
||||
CommandOk = "ok" // Confirm checker movement and pass turn to next player.
|
||||
CommandRematch = "rematch" // Confirm checker movement and pass turn to next player.
|
||||
CommandBoard = "board" // Print current board state in human-readable form.
|
||||
CommandPong = "pong" // Response to server ping.
|
||||
CommandDisconnect = "disconnect" // Disconnect from server.
|
||||
|
|
Loading…
Reference in a new issue