100 lines
1.9 KiB
Go
100 lines
1.9 KiB
Go
package main
|
|
|
|
import "fmt"
|
|
|
|
type GameResult int
|
|
|
|
const (
|
|
GameOngoing GameResult = iota
|
|
WhiteWins
|
|
BlackWins
|
|
Draw
|
|
)
|
|
|
|
type Game struct {
|
|
Board *Board
|
|
Turn int
|
|
Over bool
|
|
Result GameResult
|
|
MoveNum int
|
|
}
|
|
|
|
func NewGame() *Game {
|
|
return &Game{
|
|
Board: NewBoard(),
|
|
Turn: White,
|
|
Over: false,
|
|
Result: GameOngoing,
|
|
MoveNum: 1,
|
|
}
|
|
}
|
|
|
|
func (g *Game) MakeMove(input string) (string, error) {
|
|
if g.Over {
|
|
return "", fmt.Errorf("game is over")
|
|
}
|
|
m, err := g.Board.ParseMove(input)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
s := g.Board.Grid[m.From.Row][m.From.Col]
|
|
if s.Piece == Empty || s.Color != g.Turn {
|
|
return "", fmt.Errorf("no %s piece on %s", colorName(g.Turn), algebraic(m.From))
|
|
}
|
|
legalMoves := g.Board.generateLegalMoves(g.Turn)
|
|
found := false
|
|
for _, lm := range legalMoves {
|
|
if lm.From == m.From && lm.To == m.To && lm.Promotion == m.Promotion {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
return "", fmt.Errorf("illegal move: %s", input)
|
|
}
|
|
g.Board.MoveHistory = append(g.Board.MoveHistory, input)
|
|
g.Board.applyMove(*m)
|
|
if g.Turn == White {
|
|
g.Turn = Black
|
|
g.MoveNum++
|
|
} else {
|
|
g.Turn = White
|
|
}
|
|
oppMoves := g.Board.generateLegalMoves(g.Turn)
|
|
if len(oppMoves) == 0 {
|
|
g.Over = true
|
|
if g.Board.isInCheck(g.Turn) {
|
|
if g.Turn == White {
|
|
g.Result = BlackWins
|
|
} else {
|
|
g.Result = WhiteWins
|
|
}
|
|
} else {
|
|
g.Result = Draw
|
|
}
|
|
}
|
|
return input, nil
|
|
}
|
|
|
|
func (g *Game) Render() string {
|
|
out := g.Board.Display(g.Turn)
|
|
if g.Over {
|
|
switch g.Result {
|
|
case WhiteWins:
|
|
out += "\n === CHECKMATE! WHITE WINS! ===\n"
|
|
case BlackWins:
|
|
out += "\n === CHECKMATE! BLACK WINS! ===\n"
|
|
case Draw:
|
|
out += "\n === STALEMATE! DRAW ===\n"
|
|
}
|
|
} else {
|
|
out += fmt.Sprintf("\n Move %d | %s to move\n", g.MoveNum, colorName(g.Turn))
|
|
}
|
|
return out
|
|
}
|
|
|
|
func algebraic(p Position) string {
|
|
return string(rune('a'+p.Col)) + string(rune('0'+(8-p.Row)))
|
|
}
|
|
|