Sliding pieces moves are now illegal if after piece of same color
This commit is contained in:
@@ -145,38 +145,11 @@ public class Board: CustomStringConvertible, EventDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func move(src: String, dst: String) throws {
|
public func move(src: String, dst: String) throws {
|
||||||
guard src.count < 3 else {
|
if let from = try Square.Position(with: src),
|
||||||
throw MoveFailure.squareANIsTooLong(an: src)
|
let to = try Square.Position(with: dst)
|
||||||
|
{
|
||||||
|
try move(src: from, dst: to)
|
||||||
}
|
}
|
||||||
guard src.count > 1 else {
|
|
||||||
throw MoveFailure.squareANIsTooShort(an: src)
|
|
||||||
}
|
|
||||||
guard dst.count < 3 else {
|
|
||||||
throw MoveFailure.squareANIsTooLong(an: dst)
|
|
||||||
}
|
|
||||||
guard dst.count > 1 else {
|
|
||||||
throw MoveFailure.squareANIsTooShort(an: dst)
|
|
||||||
}
|
|
||||||
guard let f1 = src.first, let r1 = src.last, r1.isWholeNumber else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
guard let f2 = dst.first, let r2 = dst.last, r2.isWholeNumber else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
guard
|
|
||||||
let srcFile = Square.Position.File.init(rawValue: String(f1))?.value
|
|
||||||
else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
guard
|
|
||||||
let dstFile = Square.Position.File.init(rawValue: String(f2))?.value
|
|
||||||
else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try move(
|
|
||||||
src: Square.Position(rank: Int8(String(r1))!, file: srcFile),
|
|
||||||
dst: Square.Position(rank: Int8(String(r2))!, file: dstFile))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func move(src: Square.Position, dst: Square.Position) throws {
|
public func move(src: Square.Position, dst: Square.Position) throws {
|
||||||
|
|||||||
@@ -8,6 +8,24 @@ final class Bishop: Piece, DiagonalMoves {
|
|||||||
return getDiagonalMoves(from: position)
|
return getDiagonalMoves(from: position)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func getLegalPosition() {
|
||||||
|
legalPositions = []
|
||||||
|
var last: Square.Position? = nil
|
||||||
|
for position in pseudoLegalPositions {
|
||||||
|
if !isLegal(on: position) {
|
||||||
|
last = position
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !DiagonalDirection.isLegal(last: &last, current: position) {
|
||||||
|
last = nil
|
||||||
|
}
|
||||||
|
if last == nil {
|
||||||
|
legalPositions.append(position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override func isLegal(on pos: Square.Position) -> Bool {
|
override func isLegal(on pos: Square.Position) -> Bool {
|
||||||
super.isLegal(on: pos)
|
super.isLegal(on: pos)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
fileprivate func getDirectionalMoves(from pos: Square.Position, with dir: [(Int8, Int8)]) -> [Square.Position] {
|
private func getDirectionalMoves(
|
||||||
|
from pos: Square.Position, with dir: [(Int8, Int8)]
|
||||||
|
) -> [Square.Position] {
|
||||||
var squares = [Square.Position]()
|
var squares = [Square.Position]()
|
||||||
for i: (Int8, Int8) in dir {
|
for i: (Int8, Int8) in dir {
|
||||||
var currentSquare = pos + i
|
var currentSquare = pos + i
|
||||||
@@ -9,13 +11,61 @@ fileprivate func getDirectionalMoves(from pos: Square.Position, with dir: [(Int8
|
|||||||
}
|
}
|
||||||
return squares
|
return squares
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol DiagonalMoves {
|
protocol DiagonalMoves {
|
||||||
func getDiagonalMoves(from pos: Square.Position) -> [Square.Position]
|
func getDiagonalMoves(from pos: Square.Position) -> [Square.Position]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protocol Direction: CaseIterable {
|
||||||
|
var values: (Int8, Int8) { get }
|
||||||
|
static func isLegal(
|
||||||
|
last: inout Square.Position?,
|
||||||
|
current: Square.Position
|
||||||
|
) -> Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DiagonalDirection: Direction {
|
||||||
|
case northWest
|
||||||
|
case northEast
|
||||||
|
case southEast
|
||||||
|
case southWest
|
||||||
|
|
||||||
|
public var values: (Int8, Int8) {
|
||||||
|
return switch self {
|
||||||
|
case .northWest: (1, -1)
|
||||||
|
case .northEast: (1, 1)
|
||||||
|
case .southEast: (-1, 1)
|
||||||
|
case .southWest: (-1, -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static func isLegal(
|
||||||
|
last: inout Square.Position?,
|
||||||
|
current:
|
||||||
|
Square.Position
|
||||||
|
) -> Bool {
|
||||||
|
var isPred = false
|
||||||
|
for dir in DiagonalDirection.allCases {
|
||||||
|
isPred = last == current - dir.values
|
||||||
|
if isPred {
|
||||||
|
last = current
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isPred
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension DiagonalMoves {
|
extension DiagonalMoves {
|
||||||
func getDiagonalMoves(from pos: Square.Position) -> [Square.Position] {
|
func getDiagonalMoves(from pos: Square.Position) -> [Square.Position] {
|
||||||
getDirectionalMoves(from: pos, with: [(1, -1), (1, 1), (-1, 1), (-1, -1)])
|
getDirectionalMoves(
|
||||||
|
from: pos,
|
||||||
|
with: [
|
||||||
|
DiagonalDirection.northWest.values,
|
||||||
|
DiagonalDirection.northEast.values,
|
||||||
|
DiagonalDirection.southEast.values,
|
||||||
|
DiagonalDirection.southWest.values,
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,8 +73,46 @@ protocol LinearMoves {
|
|||||||
func getLinearMoves(from pos: Square.Position) -> [Square.Position]
|
func getLinearMoves(from pos: Square.Position) -> [Square.Position]
|
||||||
}
|
}
|
||||||
|
|
||||||
extension LinearMoves {
|
public enum LinearDirection: Direction {
|
||||||
func getLinearMoves(from pos: Square.Position) -> [Square.Position] {
|
case north
|
||||||
getDirectionalMoves(from: pos, with: [(1, 0), (0, 1), (-1, 0), (0, -1)])
|
case south
|
||||||
|
case east
|
||||||
|
case west
|
||||||
|
|
||||||
|
public var values: (Int8, Int8) {
|
||||||
|
return switch self {
|
||||||
|
case .north: (1, 0)
|
||||||
|
case .south: (-1, 0)
|
||||||
|
case .east: (0, 1)
|
||||||
|
case .west: (0, -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func isLegal(
|
||||||
|
last: inout Square.Position?, current: Square.Position
|
||||||
|
) -> Bool {
|
||||||
|
var isPred = false
|
||||||
|
for dir in LinearDirection.allCases {
|
||||||
|
isPred = last == current - dir.values
|
||||||
|
if isPred {
|
||||||
|
last = current
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isPred
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension LinearMoves {
|
||||||
|
func getLinearMoves(from pos: Square.Position) -> [Square.Position] {
|
||||||
|
getDirectionalMoves(
|
||||||
|
from: pos,
|
||||||
|
with: [
|
||||||
|
LinearDirection.north.values,
|
||||||
|
LinearDirection.east.values,
|
||||||
|
LinearDirection.south.values,
|
||||||
|
LinearDirection.west.values,
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ public class Piece: Hashable {
|
|||||||
internal var pseudoLegalPositions: [Square.Position] {
|
internal var pseudoLegalPositions: [Square.Position] {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
internal var legalPositions = [Square.Position]()
|
package internal(set) var legalPositions = [Square.Position]()
|
||||||
internal func getLegalPosition() {
|
internal func getLegalPosition() {
|
||||||
legalPositions = pseudoLegalPositions.filter { isLegal(on: $0) }
|
legalPositions = pseudoLegalPositions.filter { isLegal(on: $0) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,27 @@ final class Queen: Piece, LinearMoves, DiagonalMoves {
|
|||||||
return getDiagonalMoves(from: position) + getLinearMoves(from: position)
|
return getDiagonalMoves(from: position) + getLinearMoves(from: position)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func getLegalPosition() {
|
||||||
|
legalPositions = []
|
||||||
|
var last: Square.Position? = nil
|
||||||
|
for position in pseudoLegalPositions {
|
||||||
|
if !isLegal(on: position) {
|
||||||
|
last = position
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !LinearDirection.isLegal(last: &last, current: position)
|
||||||
|
&& !DiagonalDirection.isLegal(last: &last, current: position)
|
||||||
|
{
|
||||||
|
last = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if last == nil {
|
||||||
|
legalPositions.append(position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override func isLegal(on pos: Square.Position) -> Bool {
|
override func isLegal(on pos: Square.Position) -> Bool {
|
||||||
super.isLegal(on: pos)
|
super.isLegal(on: pos)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,24 @@ final class Rook: Piece, LinearMoves {
|
|||||||
return getLinearMoves(from: position)
|
return getLinearMoves(from: position)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func getLegalPosition() {
|
||||||
|
legalPositions = []
|
||||||
|
var last: Square.Position? = nil
|
||||||
|
for position in pseudoLegalPositions {
|
||||||
|
if !isLegal(on: position) {
|
||||||
|
last = position
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !LinearDirection.isLegal(last: &last, current: position) {
|
||||||
|
last = nil
|
||||||
|
}
|
||||||
|
if last == nil {
|
||||||
|
legalPositions.append(position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override func isLegal(on pos: Square.Position) -> Bool {
|
override func isLegal(on pos: Square.Position) -> Bool {
|
||||||
super.isLegal(on: pos)
|
super.isLegal(on: pos)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,25 @@ public struct Square: Equatable {
|
|||||||
file = f
|
file = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init?(with rep: String) throws {
|
||||||
|
guard rep.count < 3 else {
|
||||||
|
throw Board.MoveFailure.squareANIsTooLong(an: rep)
|
||||||
|
}
|
||||||
|
guard rep.count > 1 else {
|
||||||
|
throw Board.MoveFailure.squareANIsTooShort(an: rep)
|
||||||
|
}
|
||||||
|
guard let f1 = rep.first, let r1 = rep.last, r1.isWholeNumber else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
guard
|
||||||
|
let srcFile = File.init(rawValue: String(f1))?.value
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
rank = Int8(String(r1))!
|
||||||
|
file = srcFile
|
||||||
|
}
|
||||||
|
|
||||||
public enum File: String, CustomStringConvertible {
|
public enum File: String, CustomStringConvertible {
|
||||||
case a, b, c, d, e, f, g, h
|
case a, b, c, d, e, f, g, h
|
||||||
|
|
||||||
@@ -70,6 +89,22 @@ public struct Square: Equatable {
|
|||||||
public static func += (lhs: inout Position, rhs: (Int8, Int8)) {
|
public static func += (lhs: inout Position, rhs: (Int8, Int8)) {
|
||||||
lhs = lhs + rhs
|
lhs = lhs + rhs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func - (lhs: Position, rhs: Position) -> Position {
|
||||||
|
.init(rank: lhs.rank - rhs.rank, file: lhs.file - rhs.file)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func - (lhs: Position, rhs: (Int8, Int8)) -> Position {
|
||||||
|
.init(rank: lhs.rank - rhs.0, file: lhs.file - rhs.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func -= (lhs: inout Position, rhs: Position) {
|
||||||
|
lhs = lhs - rhs
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func -= (lhs: inout Position, rhs: (Int8, Int8)) {
|
||||||
|
lhs = lhs - rhs
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public let position: Position
|
public let position: Position
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ enum Command: Equatable {
|
|||||||
case move(from: String, to: String)
|
case move(from: String, to: String)
|
||||||
case history(command: String? = nil)
|
case history(command: String? = nil)
|
||||||
case highlightThreatened(color: Color)
|
case highlightThreatened(color: Color)
|
||||||
|
case highlightPositions(of: Square.Position)
|
||||||
|
|
||||||
init?(rawValue: String) {
|
init?(rawValue: String) {
|
||||||
let args = rawValue.lowercased().split(separator: " ")
|
let args = rawValue.lowercased().split(separator: " ")
|
||||||
@@ -28,16 +29,25 @@ enum Command: Equatable {
|
|||||||
case "history", "h":
|
case "history", "h":
|
||||||
self = .history()
|
self = .history()
|
||||||
case "highlight" where args.count == 2, "hi" where args.count == 2:
|
case "highlight" where args.count == 2, "hi" where args.count == 2:
|
||||||
let color: Color =
|
let color: Color? =
|
||||||
switch args[1] {
|
switch args[1] {
|
||||||
case "w", "white":
|
case "w", "white":
|
||||||
.White
|
.White
|
||||||
case "b", "black":
|
case "b", "black":
|
||||||
.Black
|
.Black
|
||||||
default:
|
default:
|
||||||
.White
|
nil
|
||||||
}
|
}
|
||||||
self = .highlightThreatened(color: color)
|
if let c = color {
|
||||||
|
self = .highlightThreatened(color: c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let position = try? Square.Position(with: String(args[1])) {
|
||||||
|
self = .highlightPositions(of: position)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return nil
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -81,6 +91,14 @@ while command != .quit {
|
|||||||
print(ts.count)
|
print(ts.count)
|
||||||
print(board.text(with: [color: Array(ts)]))
|
print(board.text(with: [color: Array(ts)]))
|
||||||
}
|
}
|
||||||
|
case .highlightPositions(let pos):
|
||||||
|
if let square = board.getSquareInfo(on: pos),
|
||||||
|
let piece =
|
||||||
|
square.piece
|
||||||
|
{
|
||||||
|
let color = Board.TerminalColors(fg: .def, bg: .green)
|
||||||
|
print(board.text(with: [color: piece.legalPositions]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user