public enum Kind: String, CaseIterable { case Pawn, Knight, Bishop, Rook, Queen, King var value: Int8 { switch self { case .Pawn: 1 case .Bishop: 3 case .Knight: 3 case .Rook: 5 case .Queen: 9 case .King: -1 } } func fenRepresentation(with color: Color) -> String { let str = switch self { case .Pawn: "P" case .Bishop: "B" case .Knight: "N" case .Rook: "R" case .Queen: "Q" case .King: "K" } return color == .White ? str : str.lowercased() } static subscript(_ c: Character) -> (Self, Color)? { let v = c.uppercased() guard v == "N" || (Self.allCases.contains { String($0.rawValue.first!) == v }) else { return nil } let kind: Self = switch v { case "P": .Pawn case "N": .Knight case "B": .Bishop case "R": .Rook case "Q": .Queen case "K": .King default: .Pawn } let color: Color = c.isUppercase ? .White : .Black return (kind, color) } } 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 { return "" } public internal(set) var kind: Kind public internal(set) var position: Square.Position internal var pseudoLegalPositions: [Square.Position] { return [] } internal var legalPositions = [Square.Position]() internal func getLegalPosition() { legalPositions = pseudoLegalPositions.filter { isLegal(on: $0) } } internal var delegate: EventDelegate? internal func move(to dst: Square.Position) throws { if !(legalPositions.contains { $0 == dst }) { throw Board.MoveFailure.destinationIsIllegal(pos: dst) } try delegate?.movePiece(self, to: dst) halfMoveCount += 1 } #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 p = s.piece { if p.color == color { return false } if let king = p as? King { #warning("It could be in check or behind another piece.") delegate?.notify(.kingInCheck(self, on: king)) return false } } } delegate?.addPieceToTarget(self, target: pos) return true } internal init(kind: Kind, on pos: Square.Position, with col: Color) { self.kind = kind self.position = pos self.color = col } /// Two pieces are equal when they share the same kind, color and position public static func == (lhs: Piece, rhs: Piece) -> Bool { return lhs.kind == rhs.kind && lhs.color == rhs.color && lhs.position == rhs.position } /// Two pieces are not equal when they either do not share the same kind, /// color or position public static func != (lhs: Piece, rhs: Piece) -> Bool { return !(lhs == rhs) } /// Checks if tho pieces are similar yet not equal. /// They are considered simmilar if they share the same color and the same kind, /// but differ in position. public static func ~= (lhs: Piece, rhs: Piece) -> Bool { return lhs.kind == rhs.kind && lhs.color == rhs.color && lhs.position != rhs.position } public func hash(into hasher: inout Hasher) { hasher.combine(kind) hasher.combine(position) hasher.combine(color) } }