mirror of
https://github.com/maaslalani/gambit.git
synced 2025-10-08 22:31:53 +02:00
feat: highlight king when in check and notify checkmates
* Implement Piece type Signed-off-by: Ayman Bagabas <ayman.bagabas@gmail.com>
This commit is contained in:
committed by
Maas Lalani
parent
19181d4ada
commit
478d8110e9
39
game/game.go
39
game/game.go
@@ -24,9 +24,11 @@ type MoveMsg struct {
|
||||
|
||||
// NotifyMsg is a message that gets emitted when the user makes a move.
|
||||
type NotifyMsg struct {
|
||||
From string
|
||||
To string
|
||||
Turn bool
|
||||
From string
|
||||
To string
|
||||
Turn bool
|
||||
Check bool
|
||||
Checkmate bool
|
||||
}
|
||||
|
||||
// Game stores the state of the chess game.
|
||||
@@ -105,12 +107,12 @@ func (m *Game) View() string {
|
||||
var rows = fen.Grid(m.board.ToFen())
|
||||
|
||||
for r := board.FirstRow; r < board.Rows; r++ {
|
||||
row := rows[r]
|
||||
row := pieces.ToPieces(rows[r])
|
||||
rr := board.LastRow - r
|
||||
|
||||
// reverse the row if the board is flipped
|
||||
if m.flipped {
|
||||
row = rows[board.LastRow-r]
|
||||
row = pieces.ToPieces(rows[board.LastRow-r])
|
||||
for i, j := 0, len(row)-1; i < j; i, j = i+1, j-1 {
|
||||
row[i], row[j] = row[j], row[i]
|
||||
}
|
||||
@@ -119,20 +121,26 @@ func (m *Game) View() string {
|
||||
|
||||
s.WriteString(Faint(fmt.Sprintf(" %d ", rr+1)) + border.Vertical)
|
||||
|
||||
for c, cell := range row {
|
||||
display := pieces.Display[cell]
|
||||
for c, piece := range row {
|
||||
whiteTurn := m.board.Wtomove
|
||||
display := piece.Display()
|
||||
check := m.board.OurKingInCheck()
|
||||
selected := position.ToSquare(r, c, m.flipped)
|
||||
|
||||
// The user selected the current cell, highlight it so they know it is
|
||||
// selected.
|
||||
// selected. If it is a check, highlight the king in red.
|
||||
if m.selected == selected {
|
||||
display = Cyan(display)
|
||||
} else if check && piece.IsKing() {
|
||||
if (whiteTurn && piece.IsWhite()) || (!whiteTurn && piece.IsBlack()) {
|
||||
display = Red(display)
|
||||
}
|
||||
}
|
||||
|
||||
// Show all the cells to which the piece may move. If it is an empty cell
|
||||
// we present a coloured dot, otherwise color the capturable piece.
|
||||
if moves.IsLegal(m.pieceMoves, selected) {
|
||||
if cell == "" {
|
||||
if piece.IsEmpty() {
|
||||
display = "."
|
||||
}
|
||||
display = Magenta(display)
|
||||
@@ -190,9 +198,12 @@ func (m *Game) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *Game) Notify(from, to string, turn bool) tea.Cmd {
|
||||
func (m *Game) Notify(from, to string, turn, check, checkmate bool) tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
return NotifyMsg{From: from, To: to, Turn: turn}
|
||||
return NotifyMsg{
|
||||
From: from, To: to, Turn: turn,
|
||||
Check: check, Checkmate: checkmate,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,16 +222,20 @@ func (m *Game) Select(square string) (tea.Model, tea.Cmd) {
|
||||
|
||||
for _, move := range m.pieceMoves {
|
||||
if move.String() == from+to {
|
||||
var cmds []tea.Cmd
|
||||
m.board.Apply(move)
|
||||
|
||||
// We have applied a new move and the chess board is in a new state.
|
||||
// We must generate the new legal moves for the new state.
|
||||
m.moves = m.board.GenerateLegalMoves()
|
||||
check := m.board.OurKingInCheck()
|
||||
checkmate := check && len(m.moves) == 0
|
||||
|
||||
// We have made a move, so we no longer have a selected piece or
|
||||
// legal moves for any selected pieces.
|
||||
g, cmd := m.Deselect()
|
||||
return g, tea.Batch(m.Notify(from, to, m.board.Wtomove), cmd)
|
||||
cmds = append(cmds, cmd, m.Notify(from, to, m.board.Wtomove, check, checkmate))
|
||||
return g, tea.Batch(cmds...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,8 +1,13 @@
|
||||
package pieces
|
||||
|
||||
// Display maps pieces from their FEN representations to their ASCII
|
||||
import "strings"
|
||||
|
||||
// Piece represents a chess piece.
|
||||
type Piece string
|
||||
|
||||
// display maps pieces from their FEN representations to their ASCII
|
||||
// representations for a more human readable experience.
|
||||
var Display = map[string]string{
|
||||
var display = map[Piece]string{
|
||||
"": " ",
|
||||
"B": "♝",
|
||||
"K": "♚",
|
||||
@@ -17,3 +22,69 @@ var Display = map[string]string{
|
||||
"q": "♕",
|
||||
"r": "♖",
|
||||
}
|
||||
|
||||
// IsWhite returns true if the piece is white.
|
||||
func (p Piece) IsWhite() bool {
|
||||
s := p.String()
|
||||
return strings.ToUpper(s) == s
|
||||
}
|
||||
|
||||
// IsBlack returns true if the piece is black.
|
||||
func (p Piece) IsBlack() bool {
|
||||
s := p.String()
|
||||
return strings.ToLower(s) == s
|
||||
}
|
||||
|
||||
// Display returns the ASCII representation of the piece.
|
||||
func (p Piece) Display() string {
|
||||
return display[p]
|
||||
}
|
||||
|
||||
// String implements the stringer interface.
|
||||
func (p Piece) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
// IsKing returns true if the piece is a king.
|
||||
func (p Piece) IsKing() bool {
|
||||
return p == "K" || p == "k"
|
||||
}
|
||||
|
||||
// IsPawn returns true if the piece is a pawn.
|
||||
func (p Piece) IsPawn() bool {
|
||||
return p == "P" || p == "p"
|
||||
}
|
||||
|
||||
// IsRook returns true if the piece is a rook.
|
||||
func (p Piece) IsRook() bool {
|
||||
return p == "R" || p == "r"
|
||||
}
|
||||
|
||||
// IsBishop returns true if the piece is a bishop.
|
||||
func (p Piece) IsBishop() bool {
|
||||
return p == "B" || p == "b"
|
||||
}
|
||||
|
||||
// IsKnight returns true if the piece is a knight.
|
||||
func (p Piece) IsKnight() bool {
|
||||
return p == "N" || p == "n"
|
||||
}
|
||||
|
||||
// IsQueen returns true if the piece is a queen.
|
||||
func (p Piece) IsQueen() bool {
|
||||
return p == "Q" || p == "q"
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the piece is empty.
|
||||
func (p Piece) IsEmpty() bool {
|
||||
return p == ""
|
||||
}
|
||||
|
||||
// ToPieces converts a slice of FEN string to a slice of pieces.
|
||||
func ToPieces(r [8]string) [8]Piece {
|
||||
var p [8]Piece
|
||||
for i, s := range r {
|
||||
p[i] = Piece(s)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
Reference in New Issue
Block a user