Compare commits

...

2 Commits

Author SHA1 Message Date
ekzyis ce6dd39af1 Implement pawn diagonal attack 2024-09-18 08:02:09 +02:00
ekzyis f217290b73 Better TODOs 2024-09-18 07:12:02 +02:00
2 changed files with 83 additions and 9 deletions

View File

@ -132,10 +132,46 @@ func (b *Board) Parse(pgn string) error {
func (b *Board) Move(position string) error { func (b *Board) Move(position string) error {
var ( var (
err error err error
// the column from which the piece is captured.
// for example, this would be 'e' for exd4 and 'e' for Nexd4.
captureFrom string
) )
if strings.Contains(position, "x") {
// capture move
parts := strings.Split(position, "x")
if len(parts) != 2 {
return fmt.Errorf("invalid move: %s", position)
}
if len(parts[0]) == 2 {
// example: Nexd4
captureFrom = parts[0][1:]
} else if len(parts[0]) == 1 {
if strings.ToLower(parts[0]) == parts[0] {
// example: exd4
captureFrom = parts[0]
} else {
// example: Nxd4
captureFrom = ""
}
} else {
return fmt.Errorf("invalid move: %s", position)
}
position = strings.Replace(position, captureFrom+"x", "", 1)
}
// TODO: parse captures e.g. exd5 or Nxd5
// TODO: parse promotions
// TODO: parse checks e.g. e5+
// TODO: parse checkmates e.g. e5#
// TODO: parse O-O as kingside castle and O-O-O as queenside castle
// TODO: make sure pinned pieces cannot move
// TODO: make sure king is not in check after move
// ( this avoids moving into check and moving a piece that exposes the king to check e.g. pinned pieces )
if len(position) == 2 { if len(position) == 2 {
err = b.movePawn(position) err = b.movePawn(position, captureFrom)
} else if len(position) == 3 { } else if len(position) == 3 {
switch strings.ToLower(position[0:1]) { switch strings.ToLower(position[0:1]) {
case "r": case "r":
@ -166,10 +202,12 @@ func (b *Board) Move(position string) error {
return nil return nil
} }
func (b *Board) movePawn(position string) error { func (b *Board) movePawn(position string, captureFrom string) error {
var ( var (
x int x int
y int y int
cX int
cY int
yPrev int yPrev int
piece *Piece piece *Piece
err error err error
@ -179,7 +217,38 @@ func (b *Board) movePawn(position string) error {
return err return err
} }
// TODO: implement diagonal pawn attacks if captureFrom != "" {
if cX, cY, err = getXY(captureFrom + position[0:1]); err != nil {
return err
}
if b.turn == Light {
cY = y + 1
} else {
cY = y - 1
}
piece = b.getPiece(cX, cY)
if piece == nil || piece.Name != Pawn || piece.Color != b.turn {
// not your pawn
return fmt.Errorf("invalid capture move for pawn: %s", position)
}
if cX != x-1 && cX != x+1 || (b.turn == Light && cY != y+1) || (b.turn == Dark && cY != y-1) {
// invalid capture move
return fmt.Errorf("invalid capture move for pawn: %s", position)
}
b.tiles[cX][cY] = nil
b.tiles[x][y] = piece
return nil
}
// TODO: assert move is valid:
// * 2 moves from start position
// * 1 move otherwise
// * diagonal if attacking
// * no collision with other pieces
if b.turn == Light { if b.turn == Light {
yPrev = y + 1 yPrev = y + 1
@ -207,12 +276,6 @@ func (b *Board) movePawn(position string) error {
return nil return nil
} }
// TODO: assert move is valid:
// * 2 moves from start position
// * 1 move otherwise
// * diagonal if attacking
// * no collision with other pieces
return fmt.Errorf("no pawn found that can move to %s", position) return fmt.Errorf("no pawn found that can move to %s", position)
} }

View File

@ -95,6 +95,17 @@ func TestBoardMovePawnInvalid(t *testing.T) {
assertMoveError(t, b, "h4", "no pawn found that can move to h4") assertMoveError(t, b, "h4", "no pawn found that can move to h4")
} }
func TestBoardMovePawnCapture(t *testing.T) {
b := chess.NewBoard()
b.Move("e4")
b.Move("d5")
b.Move("exd5")
assertNoPiece(t, b, "e4")
assertPiece(t, b, "d5", chess.Pawn, chess.Light)
}
func TestBoardMoveKnight(t *testing.T) { func TestBoardMoveKnight(t *testing.T) {
b := chess.NewBoard() b := chess.NewBoard()