From 78a473701568a5691ea765f39a0332277e245d45 Mon Sep 17 00:00:00 2001 From: cdricms <36056008+cdricms@users.noreply.github.com> Date: Wed, 26 Jun 2024 01:07:03 +0200 Subject: [PATCH] Test + bug fixes --- Sources/Engine/Board.swift | 109 ++-------------------------- Sources/Engine/FEN.swift | 76 +++++++++++++++++++ Sources/Engine/Square.swift | 5 +- Sources/exe/main.swift | 3 +- Tests/EngineTests/EngineTests.swift | 11 +++ 5 files changed, 100 insertions(+), 104 deletions(-) create mode 100644 Sources/Engine/FEN.swift diff --git a/Sources/Engine/Board.swift b/Sources/Engine/Board.swift index 02b3a1e..fe81c7f 100644 --- a/Sources/Engine/Board.swift +++ b/Sources/Engine/Board.swift @@ -1,79 +1,3 @@ -public struct Fen: CustomStringConvertible { - public enum CastlingAvailibility: String { - case Neither = "-" - case WhiteKingSide = "K" - case WhiteQueenSide = "Q" - case BlackKingSide = "k" - case BlackQueenSide = "q" - case WhiteSide = "KQ" - case BlackSide = "kq" - case Kings = "Kk" - case Queens = "Qq" - case WKingBQueen = "Kq" - case WQueenBKing = "Qk" - case All = "KQkq" - } - private var _fen: String = "" - private var value: String { - get { - return _fen - } - set { - _fen = newValue - let splitted = _fen.split(separator: " ") - guard splitted.count == 6 else { - return - } - placement = String(splitted[0]) - activeColor = - switch splitted[1] { - case "w": .White - case "b": .Black - default: .White - } - castlingAvailibility = - CastlingAvailibility( - rawValue: - String(splitted[2])) ?? .Neither - enPassant = String(splitted[3]) - halfMoveClock = - if let c = splitted[4].first, c.isWholeNumber { - UInt8(String(c)) ?? 0 - } else { - 0 - } - fullMoveClock = - if let c = splitted[5].first, c.isWholeNumber { - UInt8(String(c)) ?? 1 - } else { - 1 - } - } - } - - public private(set) var placement: String = "" // 70 chars - public private(set) var activeColor: Color = .White // 1 char - public private(set) var castlingAvailibility: CastlingAvailibility = .All - // 1 to 4 chars - public private(set) var enPassant: String = "-" // 1 or 2 chars - public private(set) var halfMoveClock: UInt8 = 0 - public package(set) var fullMoveClock: UInt8 = 1 - - public init(fen value: String) { - self.value = value - } - - public enum FenError: Error { - case InvalidCharacter(c: String, column: UInt8) - case NumberTooBig(n: UInt8, column: UInt8) - case NumberTooSmall(n: UInt8, column: UInt8) - } - - public var description: String { - return value - } -} - public class Board: CustomStringConvertible { public typealias Grid = [[Square]] @@ -112,6 +36,9 @@ public class Board: CustomStringConvertible { for c in fen.placement { let r = (8 - Int(rank)) % 8 if c == "/" { + if file != 9 { + throw Fen.FenError.NotAppropriateLength(n: file, column: index) + } rank -= 1 file = 0 } else if c.isWholeNumber, let n = UInt8(String(c)) { @@ -175,9 +102,13 @@ public class Board: CustomStringConvertible { rank -= 1 } } + // TODO: Handle better do { try setBoard() + } catch Fen.FenError.NotAppropriateLength(let n, let column) { + fatalError("Not appropriate length: \(n) on \(column)") } catch { + } } @@ -208,28 +139,4 @@ public class Board: CustomStringConvertible { } return squares[i] } -} - -// For now useless, learn how to setup properly -// extension Board.Grid { -// public subscript(rank: UInt8, file: UInt8) -> Square? { -// get { -// guard 1 > rank && rank < 9 && 1 > file && file < 9 else { -// return nil -// } - -// return self[(8 - Int(rank)) % 8][Int(file) - 1] -// } -// set { -// guard 1 > rank && rank < 9 && 1 > file && file < 9 else { -// return -// } - -// guard let n = newValue else { -// return -// } - -// self[(8 - Int(rank)) % 8][Int(file) - 1] = n -// } -// } -// } +} \ No newline at end of file diff --git a/Sources/Engine/FEN.swift b/Sources/Engine/FEN.swift new file mode 100644 index 0000000..aea6fc5 --- /dev/null +++ b/Sources/Engine/FEN.swift @@ -0,0 +1,76 @@ +public struct Fen: CustomStringConvertible { + public enum CastlingAvailibility: String { + case Neither = "-" + case WhiteKingSide = "K" + case WhiteQueenSide = "Q" + case BlackKingSide = "k" + case BlackQueenSide = "q" + case WhiteSide = "KQ" + case BlackSide = "kq" + case Kings = "Kk" + case Queens = "Qq" + case WKingBQueen = "Kq" + case WQueenBKing = "Qk" + case All = "KQkq" + } + private var _fen: String = "" + private var value: String { + get { + return _fen + } + set { + _fen = newValue + let splitted = _fen.split(separator: " ") + guard splitted.count == 6 else { + return + } + placement = String(splitted[0]) + activeColor = + switch splitted[1] { + case "w": .White + case "b": .Black + default: .White + } + castlingAvailibility = + CastlingAvailibility( + rawValue: + String(splitted[2])) ?? .Neither + enPassant = String(splitted[3]) + halfMoveClock = + if let c = splitted[4].first, c.isWholeNumber { + UInt8(String(c)) ?? 0 + } else { + 0 + } + fullMoveClock = + if let c = splitted[5].first, c.isWholeNumber { + UInt8(String(c)) ?? 1 + } else { + 1 + } + } + } + + public private(set) var placement: String = "" // 70 chars + public private(set) var activeColor: Color = .White // 1 char + public private(set) var castlingAvailibility: CastlingAvailibility = .All + // 1 to 4 chars + public private(set) var enPassant: String = "-" // 1 or 2 chars + public private(set) var halfMoveClock: UInt8 = 0 + public package(set) var fullMoveClock: UInt8 = 1 + + public init(fen value: String) { + self.value = value + } + + public enum FenError: Error { + case InvalidCharacter(c: String, column: UInt8) + case NumberTooBig(n: UInt8, column: UInt8) + case NumberTooSmall(n: UInt8, column: UInt8) + case NotAppropriateLength(n: UInt8, column: UInt8) + } + + public var description: String { + return value + } +} \ No newline at end of file diff --git a/Sources/Engine/Square.swift b/Sources/Engine/Square.swift index 065ab9e..2e7761e 100644 --- a/Sources/Engine/Square.swift +++ b/Sources/Engine/Square.swift @@ -5,11 +5,12 @@ public struct Square: Equatable { public let rank: UInt8 public var index: Int { - return Int(file * rank) - 1 + let r = (8 - rank) % 8 + return Int(8*r+file-1) } public static func == (lhs: Position, rhs: Position) -> Bool { - return lhs.rank == rhs.rank && lhs.file == rhs.file + return lhs.index == rhs.index } } diff --git a/Sources/exe/main.swift b/Sources/exe/main.swift index beb476f..8950a29 100644 --- a/Sources/exe/main.swift +++ b/Sources/exe/main.swift @@ -1,5 +1,6 @@ import Engine -let board = Board() +let board = Board(fen: .init(fen: "rnbqkb1r/pppppppp/2n5/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")) +// let board: Board = .init() print(board) diff --git a/Tests/EngineTests/EngineTests.swift b/Tests/EngineTests/EngineTests.swift index 5b591cb..b1c0ccd 100644 --- a/Tests/EngineTests/EngineTests.swift +++ b/Tests/EngineTests/EngineTests.swift @@ -6,6 +6,17 @@ final class EngineTests: XCTestCase { override func setUp() { super.setUp() } + func testPositionIndex() throws { + var rank = 9 + for i in 0..<64 { + let file = (i % 8) + 1 + if file - 1 == 0 { + rank -= 1 + } + let pos: Square.Position = .init(file: UInt8(file), rank: UInt8(rank)) + XCTAssertTrue(pos.index == i, "Expected \(i) got \(pos.index)") + } + } // func testBoard() throws { // let board = Board() // }