SwiftChessNeo

WIP:正在开发 swift-chess-neo,同时也在为 iOS/macOS 编写 iWatchChess

Fork 自 @nvzqzSage 以及 @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 能够为当前玩家生成合法的走棋,并完全支持特殊走棋,例如吃过路兵和王车易位。

走棋验证

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)

美观打印

BoardBitboard 类型都具有 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

Forsyth–Edwards 记谱法 (FEN)

Game.PositionBoard 类型都可以生成 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)")
    }
}

根据格位查找走棋

SequenceSquare 具有两个方法,这些方法返回一个从/到 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]

Playground 用法

棋盘快速查看

Board 遵循 CustomPlaygroundDisplayConvertible 协议。

Playground quick look

待办事项

可能的其他增强功能

许可证

原始声明

Sage 及其修改版本根据 Apache 许可证 2.0 版本 发布。