WIP:正在开发 swift-chess-neo,同时也在为 iOS/macOS 编写 iWatchChess
Fork 自 @nvzqz 的 Sage 以及 @SuperGeroy 的补丁。这个 fork 添加了 SwiftUI 视图,以及其他用户体验方面的改进。由于一些技术难题,我最终直接复制了 Sources
文件夹中的文件并将它们添加到了我的项目中。
运行一个国际象棋游戏可以很简单地通过设置一个循环来实现。
import SwiftChessNeo
let game = Game()
while !game.isFinished {
let move = ...
try game.execute(move: move)
}
对于 Game
实例,可以使用 execute(move:)
及其不安全但更快的同级方法 execute(uncheckedMove:)
来执行走棋。
execute(uncheckedMove:)
方法假定传入的走棋是合法的。只有当你完全确定走棋合法时,才应该调用此方法。例如,当使用 availableMoves()
返回的走棋时就属于这种情况。否则,请使用 execute(move:)
,此方法会检查传入走棋的合法性。
SwiftChessNeo 能够为当前玩家生成合法的走棋,并完全支持特殊走棋,例如吃过路兵和王车易位。
availableMoves()
将返回当前所有可用的走棋。
movesForPiece(at:)
将返回位于特定格位的棋子的所有走棋。
movesBitboardForPiece(at:)
将返回一个 Bitboard
,其中包含位于特定格位的棋子可以移动到的所有格位。
SwiftChessNeo 还可以使用 Game
状态的 isLegal(move:)
方法来验证走棋是否合法。
execute(move:)
方法族会调用此方法,因此直接执行走棋并捕获非法走棋的任何错误会更快。
走棋的撤销和重做操作通过 undoMove()
和 redoMove()
方法完成。被撤销或重做的走棋会被返回。
要仅检查要撤销或重做的走棋,可以使用 moveToUndo()
和 moveToRedo()
方法。
execute(move:promotion:)
方法接受一个闭包,该闭包返回升变棋子类型。这允许应用程序提示用户选择升变棋子或在选择升变棋子类型之前执行任何其他操作。
try game.execute(move: move) {
...
return .queen
}
仅当走棋为兵升变时,才会执行此闭包。如果升变棋子类型无法升变兵,例如国王或兵,则会抛出错误。
也可以在不使用闭包的情况下给出棋子类型。默认类型为皇后。
try game.execute(move: move, promotion: .queen)
Board
和 Bitboard
类型都具有 ascii
属性,可用于打印可视化棋盘。
let board = Board()
board.ascii
// +-----------------+
// 8 | r n b q k b n r |
// 7 | p p p p p p p p |
// 6 | . . . . . . . . |
// 5 | . . . . . . . . |
// 4 | . . . . . . . . |
// 3 | . . . . . . . . |
// 2 | P P P P P P P P |
// 1 | R N B Q K B N R |
// +-----------------+
// a b c d e f g h
board.occupiedSpaces.ascii
// +-----------------+
// 8 | 1 1 1 1 1 1 1 1 |
// 7 | 1 1 1 1 1 1 1 1 |
// 6 | . . . . . . . . |
// 5 | . . . . . . . . |
// 4 | . . . . . . . . |
// 3 | . . . . . . . . |
// 2 | 1 1 1 1 1 1 1 1 |
// 1 | 1 1 1 1 1 1 1 1 |
// +-----------------+
// a b c d e f g h
Game.Position
和 Board
类型都可以生成 FEN 字符串。
let game = Game()
game.position.fen()
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
game.board.fen()
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR
它们也可以从 FEN 字符串初始化。
assert(Board(fen: game.board.fen()) == game.board)
assert(Game.Position(fen: game.position.fen()) == game.position)
Board
类型遵循 Sequence
协议,使遍历其空间变得无缝。
for space in Board() {
if let piece = space.piece {
print("\(piece) at \(space.square)")
}
}
Sequence
和 Square
具有两个方法,这些方法返回一个从/到 self
到/从参数的走棋数组。
[.a1, .h3, .b5].moves(from: .b4)
// [b4 >>> a1, b4 >>> h3, b4 >>> b5]
[.c3, .d2, .f1].moves(to: .a6)
// [c3 >>> a6, d2 >>> a6, f1 >>> a6]
Square.d4.moves(from: [.c2, .f8, .h2])
// [c2 >>> d4, f8 >>> d4, h2 >>> d4]
Square.a4.moves(to: [.c3, .d4, .f6])
// [a4 >>> c3, a4 >>> d4, a4 >>> f6]
Board
遵循 CustomPlaygroundDisplayConvertible
协议。
原始声明
Sage 及其修改版本根据 Apache 许可证 2.0 版本 发布。