180 lines
4.9 KiB
Go
180 lines
4.9 KiB
Go
package types
|
|
|
|
import (
|
|
"github.com/samber/lo"
|
|
)
|
|
|
|
// 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
|
|
)
|
|
|
|
type CoordinateBuilder struct {
|
|
coordinate Coordinate
|
|
}
|
|
|
|
func newCoordinateBuilder(c Coordinate) *CoordinateBuilder {
|
|
return &CoordinateBuilder{
|
|
coordinate: c,
|
|
}
|
|
}
|
|
|
|
func (b *CoordinateBuilder) Up(number int) *CoordinateBuilder {
|
|
b.coordinate.Row += number
|
|
return b
|
|
}
|
|
|
|
func (b *CoordinateBuilder) Down(number int) *CoordinateBuilder {
|
|
b.coordinate.Row -= number
|
|
return b
|
|
}
|
|
|
|
func (b *CoordinateBuilder) Left(number int) *CoordinateBuilder {
|
|
b.coordinate.Col -= number
|
|
return b
|
|
}
|
|
|
|
func (b *CoordinateBuilder) Right(number int) *CoordinateBuilder {
|
|
b.coordinate.Col += number
|
|
return b
|
|
}
|
|
|
|
func (b *CoordinateBuilder) Resolve() *Coordinate {
|
|
c := b.coordinate
|
|
if c.Row <= RangeLastValid &&
|
|
c.Row >= RangeFirstValid &&
|
|
c.Col <= RangeLastValid &&
|
|
c.Col >= RangeFirstValid {
|
|
return &c
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *Coordinate) GetAllKingMoves() []Coordinate {
|
|
squares := make([]*Coordinate, 0, 8)
|
|
|
|
squares = append(squares, c.Up(1))
|
|
squares = append(squares, c.Down(1))
|
|
squares = append(squares, c.Left(1))
|
|
squares = append(squares, c.Right(1))
|
|
|
|
squares = append(squares, newCoordinateBuilder(*c).Up(1).Right(1).Resolve())
|
|
squares = append(squares, newCoordinateBuilder(*c).Up(1).Left(1).Resolve())
|
|
squares = append(squares, newCoordinateBuilder(*c).Down(1).Right(1).Resolve())
|
|
squares = append(squares, newCoordinateBuilder(*c).Down(1).Left(1).Resolve())
|
|
|
|
return filterNilSquares(squares)
|
|
}
|
|
|
|
func (c *Coordinate) GetAllKnightMoves() []Coordinate {
|
|
unfilteredMoves := make([]*Coordinate, 0, 8)
|
|
|
|
unfilteredMoves = append(unfilteredMoves, newCoordinateBuilder(*c).Up(2).Right(1).Resolve())
|
|
unfilteredMoves = append(unfilteredMoves, newCoordinateBuilder(*c).Up(1).Right(2).Resolve())
|
|
unfilteredMoves = append(unfilteredMoves, newCoordinateBuilder(*c).Down(1).Right(2).Resolve())
|
|
unfilteredMoves = append(unfilteredMoves, newCoordinateBuilder(*c).Down(2).Right(1).Resolve())
|
|
unfilteredMoves = append(unfilteredMoves, newCoordinateBuilder(*c).Down(2).Left(1).Resolve())
|
|
unfilteredMoves = append(unfilteredMoves, newCoordinateBuilder(*c).Down(1).Left(2).Resolve())
|
|
unfilteredMoves = append(unfilteredMoves, newCoordinateBuilder(*c).Up(1).Left(2).Resolve())
|
|
unfilteredMoves = append(unfilteredMoves, newCoordinateBuilder(*c).Up(2).Left(1).Resolve())
|
|
|
|
return filterNilSquares(unfilteredMoves)
|
|
}
|
|
|
|
func filterNilSquares(squares []*Coordinate) []Coordinate {
|
|
return lo.FilterMap(squares, func(square *Coordinate, _ int) (Coordinate, bool) {
|
|
if square != nil {
|
|
return *square, true
|
|
}
|
|
return Coordinate{}, false
|
|
})
|
|
}
|
|
|
|
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 <= RangeLastValid {
|
|
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
|
|
}
|
|
|
|
func (c Coordinate) GetAllSquaresOnStraights() []Coordinate {
|
|
squares := c.GetStraightInDirection(Coordinate.Up)
|
|
squares = append(squares, c.GetStraightInDirection(Coordinate.Down)...)
|
|
squares = append(squares, c.GetStraightInDirection(Coordinate.Left)...)
|
|
squares = append(squares, c.GetStraightInDirection(Coordinate.Right)...)
|
|
return squares
|
|
}
|
|
|
|
func (c Coordinate) GetAllSquaresOnDiagonals() []Coordinate {
|
|
squares := c.GetDiagonalInDirection(Coordinate.Up, Coordinate.Right)
|
|
squares = append(squares, c.GetDiagonalInDirection(Coordinate.Down, Coordinate.Right)...)
|
|
squares = append(squares, c.GetDiagonalInDirection(Coordinate.Down, Coordinate.Left)...)
|
|
squares = append(squares, c.GetDiagonalInDirection(Coordinate.Up, Coordinate.Left)...)
|
|
return squares
|
|
}
|
|
|
|
func (c Coordinate) GetStraightInDirection(dirFn func(Coordinate, int) *Coordinate) []Coordinate {
|
|
squares := []Coordinate{}
|
|
i := 1
|
|
for {
|
|
if square := dirFn(c, i); square != nil {
|
|
squares = append(squares, *square)
|
|
i += 1
|
|
} else {
|
|
return squares
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c Coordinate) GetDiagonalInDirection(dirFn1, dirFn2 func(Coordinate, int) *Coordinate) []Coordinate {
|
|
squares := []Coordinate{}
|
|
i := 1
|
|
for {
|
|
if squareRight := dirFn1(c, i); squareRight != nil {
|
|
if square := dirFn2(*squareRight, i); square != nil {
|
|
squares = append(squares, *square)
|
|
i += 1
|
|
} else {
|
|
break
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
return squares
|
|
}
|