Pieces are now an interface and starting to enforce rules.
This commit is contained in:
parent
d5b8bdf630
commit
7f206b15fe
19
api/move.go
19
api/move.go
@ -6,19 +6,21 @@ import (
|
||||
)
|
||||
|
||||
type WebsocketMessage struct {
|
||||
Type MessageType `json:"messageType"`
|
||||
Move *types.Move `json:"move,omitempty"`
|
||||
Color *types.ChessColor `json:"color,omitempty"`
|
||||
Type MessageType `json:"messageType"`
|
||||
Move *types.Move `json:"move,omitempty"`
|
||||
Color *types.ChessColor `json:"color,omitempty"`
|
||||
Reason *string `json:"reason,omitempty"`
|
||||
}
|
||||
|
||||
type MessageType string
|
||||
|
||||
const (
|
||||
MoveMessage MessageType = "move"
|
||||
ColorDetermined MessageType = "colorDetermined"
|
||||
MoveMessage MessageType = "move"
|
||||
InvalidMoveMessage MessageType = "invalidMove"
|
||||
ColorDetermined MessageType = "colorDetermined"
|
||||
)
|
||||
|
||||
func (m WebsocketMessage) IsValidMove() bool {
|
||||
func (m WebsocketMessage) IsValidMoveMessage() bool {
|
||||
if m.Type != MoveMessage {
|
||||
return false
|
||||
}
|
||||
@ -30,5 +32,8 @@ func (m WebsocketMessage) IsValidMove() bool {
|
||||
|
||||
func GetColorDeterminedMessage(color types.ChessColor) ([]byte, error) {
|
||||
return json.Marshal(WebsocketMessage{Type: ColorDetermined, Color: &color})
|
||||
|
||||
}
|
||||
|
||||
func GetInvalidMoveMessage(move types.Move, reason string) ([]byte, error) {
|
||||
return json.Marshal(WebsocketMessage{Type: InvalidMoveMessage, Move: &move, Reason: &reason})
|
||||
}
|
||||
|
18
chess/bishop.go
Normal file
18
chess/bishop.go
Normal file
@ -0,0 +1,18 @@
|
||||
package chess
|
||||
|
||||
import "local/m/mchess_server/types"
|
||||
|
||||
type Bishop struct {
|
||||
Color types.ChessColor
|
||||
}
|
||||
|
||||
func (Bishop) AfterMoveAction() {
|
||||
}
|
||||
|
||||
func (b Bishop) GetColor() types.ChessColor {
|
||||
return b.Color
|
||||
}
|
||||
|
||||
func (b Bishop) GetAllLegalAndIllegalMoves(board Board, fromSquare types.Coordinate) []types.Coordinate {
|
||||
return []types.Coordinate{}
|
||||
}
|
114
chess/board.go
114
chess/board.go
@ -1,8 +1,12 @@
|
||||
package chess
|
||||
|
||||
import "local/m/mchess_server/types"
|
||||
import (
|
||||
"local/m/mchess_server/types"
|
||||
|
||||
type Board map[types.Coordinate]types.Piece
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
type Board map[types.Coordinate]Piece
|
||||
|
||||
func (b Board) Init() {
|
||||
var coord types.Coordinate
|
||||
@ -10,73 +14,71 @@ func (b Board) Init() {
|
||||
for i := 1; i <= 8; i++ {
|
||||
coord.Row = 2
|
||||
coord.Col = i
|
||||
b[coord] = types.Piece{Class: types.Pawn, Color: types.White}
|
||||
b[coord] = Pawn{Color: types.White, HasMoved: false}
|
||||
|
||||
coord.Row = 7
|
||||
coord.Col = i
|
||||
b[coord] = types.Piece{Class: types.Pawn, Color: types.Black}
|
||||
b[coord] = Pawn{Color: types.Black, HasMoved: false}
|
||||
}
|
||||
|
||||
b[types.Coordinate{Row: 1, Col: 1}] = types.Piece{Class: types.Rook, Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 2}] = types.Piece{Class: types.Knight, Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 3}] = types.Piece{Class: types.Bishop, Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 4}] = types.Piece{Class: types.Queen, Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 5}] = types.Piece{Class: types.King, Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 6}] = types.Piece{Class: types.Bishop, Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 7}] = types.Piece{Class: types.Knight, Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 8}] = types.Piece{Class: types.Rook, Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 1}] = Rook{Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 2}] = Knight{Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 3}] = Bishop{Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 4}] = Queen{Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 5}] = King{Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 6}] = Bishop{Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 7}] = Knight{Color: types.White}
|
||||
b[types.Coordinate{Row: 1, Col: 8}] = Rook{Color: types.White}
|
||||
|
||||
b[types.Coordinate{Row: 8, Col: 1}] = types.Piece{Class: types.Rook, Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 2}] = types.Piece{Class: types.Knight, Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 3}] = types.Piece{Class: types.Bishop, Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 4}] = types.Piece{Class: types.Queen, Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 5}] = types.Piece{Class: types.King, Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 6}] = types.Piece{Class: types.Bishop, Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 7}] = types.Piece{Class: types.Knight, Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 8}] = types.Piece{Class: types.Rook, Color: types.Black}
|
||||
}
|
||||
|
||||
func (b Board) GetPieceAt(coord types.Coordinate) (types.Piece, bool) {
|
||||
piece, found := b[coord]
|
||||
|
||||
if !found {
|
||||
piece = types.Piece{}
|
||||
}
|
||||
|
||||
return piece, found
|
||||
b[types.Coordinate{Row: 8, Col: 1}] = Rook{Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 2}] = Knight{Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 3}] = Bishop{Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 4}] = Queen{Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 5}] = King{Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 6}] = Bishop{Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 7}] = Knight{Color: types.Black}
|
||||
b[types.Coordinate{Row: 8, Col: 8}] = Rook{Color: types.Black}
|
||||
}
|
||||
|
||||
func (b Board) CheckMove(move types.Move) (bool, string) {
|
||||
pieceAtStartSquare, found := b.GetPieceAt(move.StartSquare)
|
||||
if !found {
|
||||
pieceAtStartSquare := b.getPieceAt(move.StartSquare)
|
||||
if pieceAtStartSquare == nil {
|
||||
return false, "no piece at start square"
|
||||
}
|
||||
movingColor := pieceAtStartSquare.Color
|
||||
movingColor := pieceAtStartSquare.GetColor()
|
||||
|
||||
pieceAtEndSquare, found := b.GetPieceAt(move.EndSquare)
|
||||
if found {
|
||||
if pieceAtEndSquare.Color == pieceAtStartSquare.Color {
|
||||
pieceAtEndSquare := b.getPieceAt(move.EndSquare)
|
||||
if pieceAtEndSquare != nil {
|
||||
if pieceAtEndSquare.GetColor() == pieceAtStartSquare.GetColor() {
|
||||
return false, "same-coloured piece at end square"
|
||||
}
|
||||
}
|
||||
// At the moment, we do not need to check if the correct color is moving,
|
||||
//since we are only reading moves from the player whose turn it is.
|
||||
|
||||
legal := lo.Contains(pieceAtStartSquare.GetAllLegalAndIllegalMoves(b, move.StartSquare), move.EndSquare)
|
||||
if !legal {
|
||||
return false, "not a legal square"
|
||||
}
|
||||
|
||||
//Check if king of moving color is in check -> move not allowed
|
||||
//Do that by checking if the king is in a square attacked by the other color.
|
||||
oppKingCoordinate := b.getSquareOfPiece(types.Piece{
|
||||
Class: types.King,
|
||||
Color: movingColor})
|
||||
if oppKingCoordinate == nil {
|
||||
return false, string(movingColor) + " king not found"
|
||||
}
|
||||
ownKingCoordinate := b.getSquareOfPiece(King{Color: movingColor})
|
||||
if ownKingCoordinate == nil {
|
||||
return false, string(movingColor) + " king not found"
|
||||
}
|
||||
|
||||
b.isSquareAttacked(*oppKingCoordinate, movingColor.Opposite())
|
||||
kingIsAttacked := b.isSquareAttacked(*ownKingCoordinate, movingColor.Opposite())
|
||||
if kingIsAttacked {
|
||||
return false, "king is attacked after move"
|
||||
}
|
||||
|
||||
//Check for checkmate
|
||||
//Is every square that the king can move to attacked? And can no other
|
||||
//piece block? -> checkmate
|
||||
|
||||
//only check if paths of attacking pieces can be blocked
|
||||
|
||||
//Maybe for checking checkmate, we have to check the 'path' in which the
|
||||
//checkmate is given
|
||||
|
||||
@ -84,10 +86,15 @@ func (b Board) CheckMove(move types.Move) (bool, string) {
|
||||
// in this scenaria the path are all the squares between queen and king.
|
||||
// If a piece can be moved into the path, it is no checkmate
|
||||
|
||||
//We play the move
|
||||
delete(b, move.StartSquare)
|
||||
b[move.EndSquare] = pieceAtStartSquare
|
||||
|
||||
pieceAtStartSquare.AfterMoveAction()
|
||||
return true, ""
|
||||
}
|
||||
|
||||
func (b Board) getSquareOfPiece(piece types.Piece) *types.Coordinate {
|
||||
func (b Board) getSquareOfPiece(piece Piece) *types.Coordinate {
|
||||
for k, v := range b {
|
||||
if v == piece {
|
||||
return &k
|
||||
@ -97,8 +104,21 @@ func (b Board) getSquareOfPiece(piece types.Piece) *types.Coordinate {
|
||||
}
|
||||
|
||||
func (b Board) isSquareAttacked(square types.Coordinate, byColor types.ChessColor) bool {
|
||||
attacked := false
|
||||
var attackedSquares []types.Coordinate
|
||||
|
||||
//get every legal move of color to check if this square is attacked
|
||||
return attacked
|
||||
for square, piece := range b {
|
||||
attackedSquares = append(attackedSquares, piece.GetAllLegalAndIllegalMoves(b, square)...)
|
||||
}
|
||||
|
||||
return lo.Contains(attackedSquares, square)
|
||||
}
|
||||
|
||||
func (b Board) getPieceAt(coord types.Coordinate) Piece {
|
||||
piece, found := b[coord]
|
||||
|
||||
if !found {
|
||||
return nil
|
||||
}
|
||||
|
||||
return piece
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ const (
|
||||
func NewGame() *Game {
|
||||
var game Game = Game{
|
||||
id: uuid.New(),
|
||||
board: make(map[types.Coordinate]types.Piece),
|
||||
board: make(map[types.Coordinate]Piece),
|
||||
}
|
||||
game.board.Init()
|
||||
|
||||
@ -76,10 +76,18 @@ func (game *Game) Handle() {
|
||||
|
||||
case CheckMove:
|
||||
valid, reason := game.board.CheckMove(receivedMove)
|
||||
log.Println(reason)
|
||||
|
||||
if valid {
|
||||
gameState = CheckPlayerChange
|
||||
} else {
|
||||
log.Println("invalid move because " + reason)
|
||||
invalidMoveMessage, err := api.GetInvalidMoveMessage(receivedMove, reason)
|
||||
if err != nil {
|
||||
log.Println("Error marshalling 'colorDetermined' message for player 1", err)
|
||||
return
|
||||
}
|
||||
game.currentTurnPlayer.writeMessage(invalidMoveMessage)
|
||||
gameState = PlayerToMove
|
||||
}
|
||||
case CheckPlayerChange:
|
||||
if game.currentTurnPlayer.Uuid == game.players[0].Uuid {
|
||||
|
22
chess/king.go
Normal file
22
chess/king.go
Normal file
@ -0,0 +1,22 @@
|
||||
package chess
|
||||
|
||||
import "local/m/mchess_server/types"
|
||||
|
||||
type King struct {
|
||||
Color types.ChessColor
|
||||
HasMoved bool
|
||||
}
|
||||
|
||||
// AfterMoveAction implements Piece.
|
||||
func (k King) AfterMoveAction() {
|
||||
k.HasMoved = true
|
||||
}
|
||||
|
||||
// GetColor implements Piece.
|
||||
func (k King) GetColor() types.ChessColor {
|
||||
return k.Color
|
||||
}
|
||||
|
||||
func (k King) GetAllLegalAndIllegalMoves(board Board, fromSquare types.Coordinate) []types.Coordinate {
|
||||
return []types.Coordinate{}
|
||||
}
|
19
chess/knight.go
Normal file
19
chess/knight.go
Normal file
@ -0,0 +1,19 @@
|
||||
package chess
|
||||
|
||||
import "local/m/mchess_server/types"
|
||||
|
||||
type Knight struct {
|
||||
Color types.ChessColor
|
||||
}
|
||||
|
||||
// AfterMoveAction implements Piece.
|
||||
func (Knight) AfterMoveAction() {
|
||||
}
|
||||
|
||||
func (k Knight) GetColor() types.ChessColor {
|
||||
return k.Color
|
||||
}
|
||||
|
||||
func (k Knight) GetAllLegalAndIllegalMoves(board Board, fromSquare types.Coordinate) []types.Coordinate {
|
||||
return []types.Coordinate{}
|
||||
}
|
83
chess/pawn.go
Normal file
83
chess/pawn.go
Normal file
@ -0,0 +1,83 @@
|
||||
package chess
|
||||
|
||||
import (
|
||||
"local/m/mchess_server/types"
|
||||
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
type Pawn struct {
|
||||
Color types.ChessColor
|
||||
HasMoved bool
|
||||
}
|
||||
|
||||
func (p Pawn) AfterMoveAction() {
|
||||
p.HasMoved = true
|
||||
}
|
||||
|
||||
func (p Pawn) GetAllLegalAndIllegalMoves(board Board, fromSquare types.Coordinate) []types.Coordinate {
|
||||
theoreticalSquares := p.getAllMoves(fromSquare)
|
||||
legalSquares := p.filterBlockedSquares(board, fromSquare, theoreticalSquares)
|
||||
|
||||
return legalSquares
|
||||
}
|
||||
|
||||
func (p Pawn) GetColor() types.ChessColor {
|
||||
return p.Color
|
||||
}
|
||||
|
||||
func (p Pawn) getAllMoves(fromSquare types.Coordinate) []types.Coordinate {
|
||||
theoreticalMoves := make([]types.Coordinate, 0, 4)
|
||||
|
||||
switch p.Color {
|
||||
case types.Black:
|
||||
if fromSquare.Down(1) != nil {
|
||||
theoreticalMoves = append(theoreticalMoves, *fromSquare.Down(1))
|
||||
}
|
||||
if !p.HasMoved && fromSquare.Down(2) != nil {
|
||||
theoreticalMoves = append(theoreticalMoves, *fromSquare.Down(2))
|
||||
}
|
||||
|
||||
if lowerRight := fromSquare.Down(1).Right(1); lowerRight != nil {
|
||||
theoreticalMoves = append(theoreticalMoves, *lowerRight)
|
||||
}
|
||||
if lowerLeft := fromSquare.Down(1).Left(1); lowerLeft != nil {
|
||||
theoreticalMoves = append(theoreticalMoves, *lowerLeft)
|
||||
}
|
||||
|
||||
case types.White:
|
||||
if fromSquare.Up(1) != nil {
|
||||
theoreticalMoves = append(theoreticalMoves, *fromSquare.Up(1))
|
||||
}
|
||||
if !p.HasMoved && fromSquare.Up(2) != nil {
|
||||
theoreticalMoves = append(theoreticalMoves, *fromSquare.Up(2))
|
||||
}
|
||||
|
||||
if upperRight := fromSquare.Up(1).Right(1); upperRight != nil {
|
||||
theoreticalMoves = append(theoreticalMoves, *upperRight)
|
||||
}
|
||||
if upperLeft := fromSquare.Up(1).Left(1); upperLeft != nil {
|
||||
theoreticalMoves = append(theoreticalMoves, *upperLeft)
|
||||
}
|
||||
}
|
||||
|
||||
return theoreticalMoves
|
||||
}
|
||||
|
||||
func (p Pawn) filterBlockedSquares(board Board, fromSquare types.Coordinate, squaresToBeFiltered []types.Coordinate) []types.Coordinate {
|
||||
var nonBlockedSquares []types.Coordinate
|
||||
//order of movesToBeFiltered is important here
|
||||
for _, square := range squaresToBeFiltered {
|
||||
pieceAtSquare := board.getPieceAt(square)
|
||||
if square.Col == fromSquare.Col { // squares ahead
|
||||
if pieceAtSquare == nil {
|
||||
nonBlockedSquares = append(nonBlockedSquares, square)
|
||||
}
|
||||
} else { //squares that pawn attacks
|
||||
if pieceAtSquare != nil && pieceAtSquare.GetColor() != p.Color {
|
||||
nonBlockedSquares = append(nonBlockedSquares, square)
|
||||
}
|
||||
}
|
||||
}
|
||||
return lo.Intersect(nonBlockedSquares, squaresToBeFiltered)
|
||||
}
|
11
chess/piece_interface.go
Normal file
11
chess/piece_interface.go
Normal file
@ -0,0 +1,11 @@
|
||||
package chess
|
||||
|
||||
import (
|
||||
"local/m/mchess_server/types"
|
||||
)
|
||||
|
||||
type Piece interface {
|
||||
GetAllLegalAndIllegalMoves(board Board, fromSquare types.Coordinate) []types.Coordinate
|
||||
GetColor() types.ChessColor
|
||||
AfterMoveAction()
|
||||
}
|
@ -72,7 +72,7 @@ func (p *Player) ReadMove() (types.Move, error) {
|
||||
return types.Move{}, err
|
||||
}
|
||||
|
||||
if !msg.IsValidMove() {
|
||||
if !msg.IsValidMoveMessage() {
|
||||
return types.Move{}, errors.New("not a valid move")
|
||||
}
|
||||
|
||||
|
18
chess/queen.go
Normal file
18
chess/queen.go
Normal file
@ -0,0 +1,18 @@
|
||||
package chess
|
||||
|
||||
import "local/m/mchess_server/types"
|
||||
|
||||
type Queen struct {
|
||||
Color types.ChessColor
|
||||
}
|
||||
|
||||
func (Queen) AfterMoveAction() {
|
||||
}
|
||||
|
||||
func (q Queen) GetColor() types.ChessColor {
|
||||
return q.Color
|
||||
}
|
||||
|
||||
func (q Queen) GetAllLegalAndIllegalMoves(board Board, fromSquare types.Coordinate) []types.Coordinate {
|
||||
return []types.Coordinate{}
|
||||
}
|
20
chess/rook.go
Normal file
20
chess/rook.go
Normal file
@ -0,0 +1,20 @@
|
||||
package chess
|
||||
|
||||
import "local/m/mchess_server/types"
|
||||
|
||||
type Rook struct {
|
||||
Color types.ChessColor
|
||||
HasMoved bool
|
||||
}
|
||||
|
||||
func (Rook) AfterMoveAction() {
|
||||
}
|
||||
|
||||
// GetColor implements Piece.
|
||||
func (r Rook) GetColor() types.ChessColor {
|
||||
return r.Color
|
||||
}
|
||||
|
||||
func (r Rook) GetAllLegalAndIllegalMoves(board Board, fromSquare types.Coordinate) []types.Coordinate {
|
||||
return []types.Coordinate{}
|
||||
}
|
2
go.mod
2
go.mod
@ -25,10 +25,12 @@ require (
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/samber/lo v1.38.1 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.9 // indirect
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
|
||||
golang.org/x/crypto v0.5.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
|
4
go.sum
4
go.sum
@ -70,6 +70,8 @@ github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha
|
||||
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/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
|
||||
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
@ -92,6 +94,8 @@ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUu
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
|
||||
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||
|
@ -1,10 +1,50 @@
|
||||
package types
|
||||
|
||||
// coordinates starting at 1:1 and end at 8:8
|
||||
type Coordinate struct {
|
||||
Col int `json:"col"`
|
||||
Row int `json:"row"`
|
||||
}
|
||||
|
||||
const (
|
||||
RangeLastValid = 8
|
||||
RangeFirstValid = 1
|
||||
|
||||
RangeUpperInvalid = 9
|
||||
RangeLowerInvalid = 0
|
||||
)
|
||||
|
||||
func (c Coordinate) Up(number int) *Coordinate {
|
||||
check := c.Row + number
|
||||
if check <= RangeLastValid {
|
||||
return &Coordinate{Row: check, Col: c.Col}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (c Coordinate) Down(number int) *Coordinate {
|
||||
check := c.Row - number
|
||||
if check >= RangeFirstValid {
|
||||
return &Coordinate{Row: check, Col: c.Col}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Right and left is seen from a board where row 1 is on the bottom
|
||||
func (c Coordinate) Right(number int) *Coordinate {
|
||||
check := c.Col + number
|
||||
if check >= RangeFirstValid {
|
||||
return &Coordinate{Row: c.Row, Col: check}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (c Coordinate) Left(number int) *Coordinate {
|
||||
check := c.Col - number
|
||||
if check >= RangeFirstValid {
|
||||
return &Coordinate{Row: c.Row, Col: check}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Move struct {
|
||||
StartSquare Coordinate `json:"startSquare"`
|
||||
EndSquare Coordinate `json:"endSquare"`
|
||||
@ -35,9 +75,3 @@ func (c ChessColor) Opposite() ChessColor {
|
||||
return White
|
||||
}
|
||||
}
|
||||
|
||||
type Piece struct {
|
||||
Class PieceClass
|
||||
Color ChessColor
|
||||
HasMoved bool //we need this for pawns (first move is special) and rooks+king (for castling)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user