Added commands to execute interactively

This commit is contained in:
cdricms
2024-06-29 20:32:40 +02:00
parent 90f2988a14
commit 533322c5dd
4 changed files with 167 additions and 34 deletions

View File

@@ -6,6 +6,7 @@ protocol EventDelegate {
func notify(_ event: Event)
func movePiece(_ piece: Piece, to dst: Square.Position) throws
func addPieceToTarget(_ piece: Piece, target: Square.Position)
func getSquareInfo(on pos: Square.Position) -> Square?
}
public class Board: CustomStringConvertible, EventDelegate {
public typealias Grid = [[Square]]
@@ -21,6 +22,56 @@ public class Board: CustomStringConvertible, EventDelegate {
}
}
public struct TerminalColors: CustomStringConvertible, Hashable {
public enum Foreground: String {
case def = "39"
case black = "30"
case red = "31"
case green = "32"
case yellow = "33"
case blue = "34"
case magenta = "35"
case cyan = "36"
case white = "37"
}
public enum Background: String {
case def = "49"
case black = "40"
case red = "41"
case green = "42"
case yellow = "43"
case blue = "44"
case magenta = "45"
case cyan = "46"
case white = "47"
}
public var foregroundColor: Foreground? = .def
public var backgroundColor: Background? = .def
public init() {}
public init(fg: Foreground?, bg: Background) {
foregroundColor = fg
backgroundColor = bg
}
public var description: String {
var res = "\u{001B}["
if let fc = foregroundColor {
res += fc.rawValue
if backgroundColor != nil {
res += ";"
}
}
if let bc = backgroundColor {
res += bc.rawValue
}
return res + "m"
}
}
func notify(_ event: Event) {
}
@@ -38,10 +89,11 @@ public class Board: CustomStringConvertible, EventDelegate {
halfMoveClock / 2
}
internal var threatenedSquares: [Color: Set<Square.Position>] = [
.White: [],
.Black: [],
]
public internal(set) var threatenedSquares: [Color: Set<Square.Position>] =
[
.White: [],
.Black: [],
]
public internal(set) var history = History()
@@ -79,7 +131,7 @@ public class Board: CustomStringConvertible, EventDelegate {
case .destinationSquareUnreachable(let pos):
"The destination square given \(pos.rank) \(pos.file) is unreachable."
case .squareHasNoPiece(let pos):
"The square \(pos.rank) \(pos.file) doesn't have any piece to be moved."
"The square \(pos.rank) \(pos.file) doesn't have any piece."
case .destinationIsIllegal(let pos):
"The destination square given \(pos.rank) \(pos.file) is illegal to be moved to."
case .squareANIsTooLong(let an):
@@ -106,7 +158,7 @@ public class Board: CustomStringConvertible, EventDelegate {
guard let f1 = src.first, let r1 = src.last, r1.isWholeNumber else {
return
}
guard let f2 = dst.first, let r2 = src.last, r2.isWholeNumber else {
guard let f2 = dst.first, let r2 = dst.last, r2.isWholeNumber else {
return
}
guard
@@ -245,7 +297,9 @@ public class Board: CustomStringConvertible, EventDelegate {
do {
try setBoard()
for square in squares where square.piece != nil {
square.piece?.getLegalPosition()
let p = square.piece!
p.getLegalPosition()
threatenedSquares[p.color]! += Set(p.legalPositions)
}
} catch Fen.FenError.NotAppropriateLength(let n, let column) {
fatalError("Not appropriate length: \(n) on \(column)")
@@ -254,15 +308,29 @@ public class Board: CustomStringConvertible, EventDelegate {
}
}
public var description: String {
public func text(with colors: [TerminalColors: [Square.Position]]? = nil)
-> String
{
var boardString =
" A B C D E F G H \n \(UnicodeBar.TopHorizontalLine)\n"
var _rank: UInt8 = 8
let def: TerminalColors = .init()
var h1 = def
board.forEach { rank in
boardString += String(_rank) + " \(UnicodeBar.VerticalBar)"
rank.forEach { square in
let p = square.piece?.unicodeRepresentation ?? " "
boardString += " \(p) \(UnicodeBar.VerticalBar)"
if let c = colors {
for (color, s) in c {
h1 = def
if (s.contains { $0 == square.position }) {
h1 = color
break
}
}
}
boardString +=
"\(h1) \(p) \(def)\(UnicodeBar.VerticalBar)"
}
boardString += "\n"
_rank -= 1
@@ -274,6 +342,10 @@ public class Board: CustomStringConvertible, EventDelegate {
return boardString
}
public var description: String {
text()
}
internal subscript(pos: Square.Position) -> Square? {
guard let i = pos.index else {
return nil

View File

@@ -2,7 +2,7 @@ final class King: Piece {
typealias Threats = (Piece?, Piece?)
var threats: Threats = (nil, nil)
override var unicodeRepresentation: String {
return color == .Black ? "" : ""
return color == .Black ? "" : ""
}
override var pseudoLegalPositions: [Square.Position] {

View File

@@ -55,7 +55,6 @@ public enum Kind: String, CaseIterable {
public class Piece: Hashable {
#warning("TODO: To be removed, handle everything through the delegate")
internal weak var board: Board?
public internal(set) var color: Color
public internal(set) var halfMoveCount: UInt8 = 0
public var unicodeRepresentation: String {
@@ -73,7 +72,7 @@ public class Piece: Hashable {
internal var delegate: EventDelegate?
internal func move(to dst: Square.Position) throws {
if !(legalPositions.contains { $0 == dst }) {
guard (legalPositions.contains { $0 == dst }) else {
throw Board.MoveFailure.destinationIsIllegal(pos: dst)
}
@@ -83,7 +82,7 @@ public class Piece: Hashable {
#warning("This method should be better thought out.")
internal func isLegal(on pos: Square.Position) -> Bool {
if let board = board, let s = board[pos] {
if let s = delegate?.getSquareInfo(on: pos) {
if let p = s.piece {
if p.color == color { return false }
if let king = p as? King {