Add simple pawn move + tests
This commit is contained in:
parent
f1ab0c2af4
commit
b29034bab0
|
@ -7,14 +7,16 @@ import (
|
||||||
"image/png"
|
"image/png"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Board struct {
|
type Board struct {
|
||||||
tiles [8][8]*Piece
|
tiles [8][8]*Piece
|
||||||
|
turn Color
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBoard() *Board {
|
func NewBoard() *Board {
|
||||||
board := &Board{}
|
board := &Board{turn: Light}
|
||||||
|
|
||||||
board.mustSetPiece(Rook, Light, "a1")
|
board.mustSetPiece(Rook, Light, "a1")
|
||||||
board.mustSetPiece(Knight, Light, "b1")
|
board.mustSetPiece(Knight, Light, "b1")
|
||||||
|
@ -112,12 +114,100 @@ func (b *Board) SetPiece(name PieceName, color Color, position string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Board) Parse(pgn string) error {
|
||||||
|
var (
|
||||||
|
moves = strings.Split(pgn, " ")
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, move := range moves {
|
||||||
|
if err = b.Move(move); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Board) Move(position string) error {
|
||||||
|
var (
|
||||||
|
name PieceName
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: implement remaining moveset of pieces
|
||||||
|
if len(position) == 2 {
|
||||||
|
name = Pawn
|
||||||
|
}
|
||||||
|
|
||||||
|
switch name {
|
||||||
|
case Pawn:
|
||||||
|
err = b.movePawn(position)
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("invalid move: %s", position)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.turn == Light {
|
||||||
|
b.turn = Dark
|
||||||
|
} else {
|
||||||
|
b.turn = Light
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Board) movePawn(position string) error {
|
||||||
|
var (
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
piece *Piece
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if x, y, err = getXY(position); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement diagonal pawn attacks
|
||||||
|
|
||||||
|
for yi := 0; yi < 8; yi++ {
|
||||||
|
piece = b.tiles[x][yi]
|
||||||
|
if piece != nil && piece.Name == Pawn && piece.Color == b.turn {
|
||||||
|
// TODO: assert move is valid:
|
||||||
|
// * 2 moves from start position
|
||||||
|
// * 1 move otherwise
|
||||||
|
// * diagonal if attacking
|
||||||
|
b.tiles[x][y] = piece
|
||||||
|
b.tiles[x][yi] = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Board) mustSetPiece(name PieceName, color Color, position string) {
|
func (b *Board) mustSetPiece(name PieceName, color Color, position string) {
|
||||||
if err := b.SetPiece(name, color, position); err != nil {
|
if err := b.SetPiece(name, color, position); err != nil {
|
||||||
log.Fatalf("cannot set piece %s: %v", name, err)
|
log.Fatalf("cannot set piece %s: %v", name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Board) At(position string) *Piece {
|
||||||
|
var (
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if x, y, err = getXY(position); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return b.tiles[x][y]
|
||||||
|
}
|
||||||
|
|
||||||
func getXY(position string) (int, int, error) {
|
func getXY(position string) (int, int, error) {
|
||||||
var (
|
var (
|
||||||
posX rune
|
posX rune
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
package chess_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ekzyis/sn-chess/chess"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// change working directory to the root of the project
|
||||||
|
// so assets/ can be found
|
||||||
|
wd, _ := os.Getwd()
|
||||||
|
os.Chdir(path.Dir(wd))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBoardInitial(t *testing.T) {
|
||||||
|
b := chess.NewBoard()
|
||||||
|
|
||||||
|
assertPiece(t, b, "a1", chess.Rook, chess.Light)
|
||||||
|
assertPiece(t, b, "b1", chess.Knight, chess.Light)
|
||||||
|
assertPiece(t, b, "c1", chess.Bishop, chess.Light)
|
||||||
|
assertPiece(t, b, "d1", chess.Queen, chess.Light)
|
||||||
|
assertPiece(t, b, "e1", chess.King, chess.Light)
|
||||||
|
assertPiece(t, b, "f1", chess.Bishop, chess.Light)
|
||||||
|
assertPiece(t, b, "g1", chess.Knight, chess.Light)
|
||||||
|
assertPiece(t, b, "h1", chess.Rook, chess.Light)
|
||||||
|
|
||||||
|
assertPiece(t, b, "a2", chess.Pawn, chess.Light)
|
||||||
|
assertPiece(t, b, "b2", chess.Pawn, chess.Light)
|
||||||
|
assertPiece(t, b, "c2", chess.Pawn, chess.Light)
|
||||||
|
assertPiece(t, b, "d2", chess.Pawn, chess.Light)
|
||||||
|
assertPiece(t, b, "e2", chess.Pawn, chess.Light)
|
||||||
|
assertPiece(t, b, "f2", chess.Pawn, chess.Light)
|
||||||
|
assertPiece(t, b, "g2", chess.Pawn, chess.Light)
|
||||||
|
assertPiece(t, b, "h2", chess.Pawn, chess.Light)
|
||||||
|
|
||||||
|
assertPiece(t, b, "a8", chess.Rook, chess.Dark)
|
||||||
|
assertPiece(t, b, "b8", chess.Knight, chess.Dark)
|
||||||
|
assertPiece(t, b, "c8", chess.Bishop, chess.Dark)
|
||||||
|
assertPiece(t, b, "d8", chess.Queen, chess.Dark)
|
||||||
|
assertPiece(t, b, "e8", chess.King, chess.Dark)
|
||||||
|
assertPiece(t, b, "f8", chess.Bishop, chess.Dark)
|
||||||
|
assertPiece(t, b, "g8", chess.Knight, chess.Dark)
|
||||||
|
assertPiece(t, b, "h8", chess.Rook, chess.Dark)
|
||||||
|
|
||||||
|
assertPiece(t, b, "a7", chess.Pawn, chess.Dark)
|
||||||
|
assertPiece(t, b, "b7", chess.Pawn, chess.Dark)
|
||||||
|
assertPiece(t, b, "c7", chess.Pawn, chess.Dark)
|
||||||
|
assertPiece(t, b, "d7", chess.Pawn, chess.Dark)
|
||||||
|
assertPiece(t, b, "e7", chess.Pawn, chess.Dark)
|
||||||
|
assertPiece(t, b, "f7", chess.Pawn, chess.Dark)
|
||||||
|
assertPiece(t, b, "g7", chess.Pawn, chess.Dark)
|
||||||
|
assertPiece(t, b, "h7", chess.Pawn, chess.Dark)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBoardMovePawn(t *testing.T) {
|
||||||
|
b := chess.NewBoard()
|
||||||
|
|
||||||
|
b.Move("e4")
|
||||||
|
|
||||||
|
assertNoPiece(t, b, "e2")
|
||||||
|
assertPiece(t, b, "e4", chess.Pawn, chess.Light)
|
||||||
|
|
||||||
|
b.Move("e5")
|
||||||
|
|
||||||
|
assertNoPiece(t, b, "e7")
|
||||||
|
assertPiece(t, b, "e5", chess.Pawn, chess.Dark)
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertPiece(t *testing.T, b *chess.Board, position string, name chess.PieceName, color chess.Color) {
|
||||||
|
p := b.At(position)
|
||||||
|
|
||||||
|
c := "white"
|
||||||
|
if color == chess.Dark {
|
||||||
|
c = "black"
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := fmt.Sprintf("expected %s %s at %s", c, name, position)
|
||||||
|
|
||||||
|
assert.NotNil(t, p, msg)
|
||||||
|
assert.Equal(t, name, p.Name, msg)
|
||||||
|
assert.Equal(t, color, p.Color, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertNoPiece(t *testing.T, b *chess.Board, position string) {
|
||||||
|
p := b.At(position)
|
||||||
|
|
||||||
|
assert.Nil(t, p, "expected no piece at %s", position)
|
||||||
|
}
|
11
go.mod
11
go.mod
|
@ -2,4 +2,13 @@ module github.com/ekzyis/sn-chess
|
||||||
|
|
||||||
go 1.23.0
|
go 1.23.0
|
||||||
|
|
||||||
require golang.org/x/image v0.20.0
|
require (
|
||||||
|
github.com/stretchr/testify v1.9.0
|
||||||
|
golang.org/x/image v0.20.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -1,2 +1,12 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
|
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
|
||||||
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
|
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
Loading…
Reference in New Issue