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 WebsocketMessage struct {
|
||||||
Type MessageType `json:"messageType"`
|
Type MessageType `json:"messageType"`
|
||||||
Move *types.Move `json:"move,omitempty"`
|
Move *types.Move `json:"move,omitempty"`
|
||||||
Color *types.ChessColor `json:"color,omitempty"`
|
Color *types.ChessColor `json:"color,omitempty"`
|
||||||
|
Reason *string `json:"reason,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MessageType string
|
type MessageType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MoveMessage MessageType = "move"
|
MoveMessage MessageType = "move"
|
||||||
ColorDetermined MessageType = "colorDetermined"
|
InvalidMoveMessage MessageType = "invalidMove"
|
||||||
|
ColorDetermined MessageType = "colorDetermined"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m WebsocketMessage) IsValidMove() bool {
|
func (m WebsocketMessage) IsValidMoveMessage() bool {
|
||||||
if m.Type != MoveMessage {
|
if m.Type != MoveMessage {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -30,5 +32,8 @@ func (m WebsocketMessage) IsValidMove() bool {
|
|||||||
|
|
||||||
func GetColorDeterminedMessage(color types.ChessColor) ([]byte, error) {
|
func GetColorDeterminedMessage(color types.ChessColor) ([]byte, error) {
|
||||||
return json.Marshal(WebsocketMessage{Type: ColorDetermined, Color: &color})
|
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
|
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() {
|
func (b Board) Init() {
|
||||||
var coord types.Coordinate
|
var coord types.Coordinate
|
||||||
@ -10,73 +14,71 @@ func (b Board) Init() {
|
|||||||
for i := 1; i <= 8; i++ {
|
for i := 1; i <= 8; i++ {
|
||||||
coord.Row = 2
|
coord.Row = 2
|
||||||
coord.Col = i
|
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.Row = 7
|
||||||
coord.Col = i
|
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: 1}] = 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: 2}] = 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: 3}] = 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: 4}] = 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: 5}] = 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: 6}] = 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: 7}] = 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: 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: 1}] = 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: 2}] = 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: 3}] = 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: 4}] = 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: 5}] = 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: 6}] = 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: 7}] = Knight{Color: types.Black}
|
||||||
b[types.Coordinate{Row: 8, Col: 8}] = types.Piece{Class: types.Rook, Color: types.Black}
|
b[types.Coordinate{Row: 8, Col: 8}] = 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Board) CheckMove(move types.Move) (bool, string) {
|
func (b Board) CheckMove(move types.Move) (bool, string) {
|
||||||
pieceAtStartSquare, found := b.GetPieceAt(move.StartSquare)
|
pieceAtStartSquare := b.getPieceAt(move.StartSquare)
|
||||||
if !found {
|
if pieceAtStartSquare == nil {
|
||||||
return false, "no piece at start square"
|
return false, "no piece at start square"
|
||||||
}
|
}
|
||||||
movingColor := pieceAtStartSquare.Color
|
movingColor := pieceAtStartSquare.GetColor()
|
||||||
|
|
||||||
pieceAtEndSquare, found := b.GetPieceAt(move.EndSquare)
|
pieceAtEndSquare := b.getPieceAt(move.EndSquare)
|
||||||
if found {
|
if pieceAtEndSquare != nil {
|
||||||
if pieceAtEndSquare.Color == pieceAtStartSquare.Color {
|
if pieceAtEndSquare.GetColor() == pieceAtStartSquare.GetColor() {
|
||||||
return false, "same-coloured piece at end square"
|
return false, "same-coloured piece at end square"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// At the moment, we do not need to check if the correct color is moving,
|
// 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.
|
//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
|
//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.
|
//Do that by checking if the king is in a square attacked by the other color.
|
||||||
oppKingCoordinate := b.getSquareOfPiece(types.Piece{
|
ownKingCoordinate := b.getSquareOfPiece(King{Color: movingColor})
|
||||||
Class: types.King,
|
if ownKingCoordinate == nil {
|
||||||
Color: movingColor})
|
return false, string(movingColor) + " king not found"
|
||||||
if oppKingCoordinate == 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
|
//Check for checkmate
|
||||||
//Is every square that the king can move to attacked? And can no other
|
//Is every square that the king can move to attacked? And can no other
|
||||||
//piece block? -> checkmate
|
//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
|
//Maybe for checking checkmate, we have to check the 'path' in which the
|
||||||
//checkmate is given
|
//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.
|
// 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
|
// 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, ""
|
return true, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Board) getSquareOfPiece(piece types.Piece) *types.Coordinate {
|
func (b Board) getSquareOfPiece(piece Piece) *types.Coordinate {
|
||||||
for k, v := range b {
|
for k, v := range b {
|
||||||
if v == piece {
|
if v == piece {
|
||||||
return &k
|
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 {
|
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
|
for square, piece := range b {
|
||||||
return attacked
|
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 {
|
func NewGame() *Game {
|
||||||
var game Game = Game{
|
var game Game = Game{
|
||||||
id: uuid.New(),
|
id: uuid.New(),
|
||||||
board: make(map[types.Coordinate]types.Piece),
|
board: make(map[types.Coordinate]Piece),
|
||||||
}
|
}
|
||||||
game.board.Init()
|
game.board.Init()
|
||||||
|
|
||||||
@ -76,10 +76,18 @@ func (game *Game) Handle() {
|
|||||||
|
|
||||||
case CheckMove:
|
case CheckMove:
|
||||||
valid, reason := game.board.CheckMove(receivedMove)
|
valid, reason := game.board.CheckMove(receivedMove)
|
||||||
log.Println(reason)
|
|
||||||
|
|
||||||
if valid {
|
if valid {
|
||||||
gameState = CheckPlayerChange
|
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:
|
case CheckPlayerChange:
|
||||||
if game.currentTurnPlayer.Uuid == game.players[0].Uuid {
|
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
|
return types.Move{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !msg.IsValidMove() {
|
if !msg.IsValidMoveMessage() {
|
||||||
return types.Move{}, errors.New("not a valid move")
|
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/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.6 // 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/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.9 // indirect
|
github.com/ugorji/go/codec v1.2.9 // indirect
|
||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
|
||||||
golang.org/x/crypto v0.5.0 // 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/net v0.7.0 // indirect
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
|
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
|
||||||
golang.org/x/sys v0.5.0 // 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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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/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.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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
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.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 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
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-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.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||||
|
@ -1,10 +1,50 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
|
// coordinates starting at 1:1 and end at 8:8
|
||||||
type Coordinate struct {
|
type Coordinate struct {
|
||||||
Col int `json:"col"`
|
Col int `json:"col"`
|
||||||
Row int `json:"row"`
|
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 {
|
type Move struct {
|
||||||
StartSquare Coordinate `json:"startSquare"`
|
StartSquare Coordinate `json:"startSquare"`
|
||||||
EndSquare Coordinate `json:"endSquare"`
|
EndSquare Coordinate `json:"endSquare"`
|
||||||
@ -35,9 +75,3 @@ func (c ChessColor) Opposite() ChessColor {
|
|||||||
return White
|
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