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.9 KiB
141 lines
3.9 KiB
package main |
|
|
|
import ( |
|
"fmt" |
|
"image/color" |
|
"os" |
|
"strings" |
|
"time" |
|
|
|
chess "git.nightmare.haus/rudi/chessv2" |
|
"git.nightmare.haus/rudi/chessv2/image" |
|
"samhofi.us/x/keybase/v2/types/chat1" |
|
) |
|
|
|
func chessCommand(m chat1.MsgSummary) { |
|
defer log.PanicSafe() |
|
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 |
|
saveConfig() |
|
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.MovesHistory()) != 0 { |
|
// write board SVG to file |
|
yellow := color.RGBA{255, 255, 0, 1} |
|
lastMove := g.Game.MovesHistory()[len(g.Game.MovesHistory())-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() |
|
defer saveConfig() |
|
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.GameOutcome() != chess.NoOutcome { |
|
k.SendMessageByConvID(m.ConvID, fmt.Sprintf("Game completed in %+v. %s by %s.\n", time.Since(g.StartTime), g.Game.GameOutcome(), g.Game.OutcomeMethod())) |
|
delete(config.Games, g.ConvID) |
|
} |
|
go showBoard(m, g) |
|
}
|
|
|