You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
3.8 KiB
141 lines
3.8 KiB
4 years ago
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"image/color"
|
||
|
"os"
|
||
|
"strings"
|
||
|
"time"
|
||
|
|
||
|
"github.com/notnil/chess"
|
||
|
"github.com/notnil/chess/image"
|
||
|
"samhofi.us/x/keybase/v2/types/chat1"
|
||
|
)
|
||
|
|
||
|
func chessCommand(m chat1.MsgSummary) {
|
||
|
defer log.PanicSafe()
|
||
|
defer saveConfig()
|
||
|
convID := string(m.ConvID)
|
||
|
parts := strings.Split(m.Content.Text.Body, " ")
|
||
|
if g, ok := config.Games[convID]; ok {
|
||
|
if len(parts) != 2 {
|
||
|
return
|
||
|
}
|
||
|
if parts[1] == "show" {
|
||
|
go showBoard(m, &g)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
submitMove(m, &g)
|
||
|
return
|
||
|
}
|
||
|
if len(parts) < 3 {
|
||
|
return
|
||
|
}
|
||
|
coin := r.Intn(100)
|
||
|
log.LogInfo(fmt.Sprintf("Coin toss resulted in %+v\n", coin))
|
||
|
var game Game
|
||
|
if coin%2 == 0 {
|
||
|
if len(parts) == 4 && parts[3] == "heads" {
|
||
|
game.White = m.Sender.Username
|
||
|
game.Black = strings.Replace(parts[2], "@", "", -1)
|
||
|
|
||
|
} else {
|
||
|
game.Black = m.Sender.Username
|
||
|
game.White = strings.Replace(parts[2], "@", "", -1)
|
||
|
}
|
||
|
} else {
|
||
|
if len(parts) == 4 && parts[3] == "heads" {
|
||
|
game.Black = m.Sender.Username
|
||
|
game.White = strings.Replace(parts[2], "@", "", -1)
|
||
|
} else {
|
||
|
game.White = m.Sender.Username
|
||
|
game.Black = strings.Replace(parts[2], "@", "", -1)
|
||
|
}
|
||
|
}
|
||
|
log.LogDebug("There are currently %+v games.\n", len(config.Games))
|
||
|
g := chess.NewGame()
|
||
|
game.Game = g
|
||
|
game.ConvID = convID
|
||
|
game.Move = true
|
||
|
game.StartTime = time.Now()
|
||
|
config.Games[convID] = game
|
||
|
k.SendMessageByConvID(m.ConvID, fmt.Sprintf("I have created a new game for this conversation @%+v is playing as White, @%+v is playing as Black.", game.White, game.Black))
|
||
|
k.SendMessageByConvID(m.ConvID, fmt.Sprintf("Possible commands are `@chessbot show` to show the board, or `@chessbot forfeit`. Otherwise I will be expecting a move in Algebraic Notation."))
|
||
|
|
||
|
}
|
||
|
|
||
|
func showBoard(m chat1.MsgSummary, g *Game) {
|
||
|
defer log.PanicSafe()
|
||
|
// create file
|
||
|
f, err := os.Create(fmt.Sprintf("/home/chessbot/chessbot/games/%+v.svg", m.ConvID))
|
||
|
if err != nil {
|
||
|
log.LogError(fmt.Sprintf("Error in ShowBoard os.Create: %+v\n", err))
|
||
|
}
|
||
|
|
||
|
// create board position
|
||
|
fenStr := g.Game.Position().String()
|
||
|
pos := &chess.Position{}
|
||
|
if err := pos.UnmarshalText([]byte(fenStr)); err != nil {
|
||
|
log.LogError(fmt.Sprintf("Error in ShowBoard pos.UnmasrhalText: %+v\n", err))
|
||
|
}
|
||
|
if len(g.Game.Moves()) != 0 {
|
||
|
// write board SVG to file
|
||
|
yellow := color.RGBA{255, 255, 0, 1}
|
||
|
lastMove := g.Game.Moves()[len(g.Game.Moves())-1]
|
||
|
|
||
|
mark := image.MarkSquares(yellow, lastMove.S1(), lastMove.S2())
|
||
|
if err := image.SVG(f, pos.Board(), mark); err != nil {
|
||
|
log.LogError("Error in ShowBoard image.SVG Mark: %+v\n", err)
|
||
|
}
|
||
|
} else {
|
||
|
if err := image.SVG(f, pos.Board()); err != nil {
|
||
|
log.LogError("Error in ShowBoard image.SVG: %+v\n", err)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
f.Close()
|
||
|
if svgToPNG(fmt.Sprintf("/home/chessbot/chessbot/games/%+v", m.ConvID)) {
|
||
|
k.UploadToConversation(m.ConvID, "", fmt.Sprintf("/home/chessbot/chessbot/games/%+v.png", m.ConvID))
|
||
|
} else {
|
||
|
k.SendMessageByConvID(m.ConvID, fmt.Sprintf("```%+v```", g.Game.Position().Board().Draw()))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func submitMove(m chat1.MsgSummary, g *Game) {
|
||
|
defer log.PanicSafe()
|
||
|
parts := strings.Split(m.Content.Text.Body, " ")
|
||
|
if g.Move {
|
||
|
if m.Sender.Username != g.White {
|
||
|
k.SendMessageByConvID(m.ConvID, "Wait your turn.")
|
||
|
return
|
||
|
}
|
||
|
} else {
|
||
|
if m.Sender.Username != g.Black {
|
||
|
k.SendMessageByConvID(m.ConvID, "Wait your turn.")
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
if parts[1] == "forfeit" || parts[1] == "surrender" {
|
||
|
if g.Move {
|
||
|
g.Game.Resign(chess.White)
|
||
|
} else {
|
||
|
g.Game.Resign(chess.Black)
|
||
|
}
|
||
|
} else {
|
||
|
err := g.Game.MoveStr(parts[1])
|
||
|
if err != nil {
|
||
|
k.SendMessageByConvID(m.ConvID, "There was an error with your move.")
|
||
|
log.LogDebug("%+v\n", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
g.Move = !g.Move
|
||
|
|
||
|
if g.Game.Outcome() != chess.NoOutcome {
|
||
|
k.SendMessageByConvID(m.ConvID, fmt.Sprintf("Game completed in %+v. %s by %s.\n", time.Since(g.StartTime), g.Game.Outcome(), g.Game.Method()))
|
||
|
delete(config.Games, g.ConvID)
|
||
|
}
|
||
|
go showBoard(m, g)
|
||
|
}
|