1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
# SwiftChessNeo
**WIP: I am actively developing swift-chess-neo while writing iWatchChess for iOS/macOS**
Fork of [Sage by @nvzqz](https://github.com/nvzqz/Sage) along with [@SuperGeroy](https://github.com/SuperGeroy)'s patches. This fork adds SwiftUI views, and other QoL improvements. Due to some technical difficulties, I ended up copying the files in the `Sources` folder and adding them to my project.
- [Usage](#usage)
- [Game Management](#game-management)
- [Move Execution](#move-execution)
- [Move Generation](#move-generation)
- [Move Validation](#move-validation)
- [Undo and Redo Moves](#undo-and-redo-moves)
- [Promotion Handling](#promotion-handling)
- [Pretty Printing](#pretty-printing)
- [Forsyth–Edwards Notation](#forsythedwards-notation)
- [Iterating Through a Board](#iterating-through-a-board)
- [Squares to Moves](#squares-to-moves)
- [Playground Usage](#playground-usage)
- [Board Quick Look](#board-quick-look)
## Usage
### Game Management
Running a chess game can be as simple as setting up a loop.
```swift
import SwiftChessNeo
let game = Game()
while !game.isFinished {
let move = ...
try game.execute(move: move)
}
```
### Move Execution
Moves for a `Game` instance can be executed with `execute(move:)` and its unsafe
(yet faster) sibling, `execute(uncheckedMove:)`.
The `execute(uncheckedMove:)` method assumes that the passed move is legal. It
should only be called if you *absolutely* know this is true. Such a case is when
using a move returned by `availableMoves()`. Otherwise use `execute(move:)`,
which checks the legality of the passed move.
### Move Generation
SwiftChessNeo is capable of generating legal moves for the current player with full
support for special moves such as en passant and castling.
- `availableMoves()` will return all moves currently available.
- `movesForPiece(at:)` will return all moves for a piece at a square.
- `movesBitboardForPiece(at:)` will return a `Bitboard` containing all of the
squares a piece at a square can move to.
### Move Validation
SwiftChessNeo can also validate whether a move is legal with the `isLegal(move:)`
method for a `Game` state.
The `execute(move:)` family of methods calls this method, so it would be faster
to execute the move directly and catch any error from an illegal move.
### Undo and Redo Moves
Move undo and redo operations are done with the `undoMove()` and `redoMove()`
methods. The undone or redone move is returned.
To just check what moves are to be undone or redone, the `moveToUndo()` and
`moveToRedo()` methods are available.
### Promotion Handling
The `execute(move:promotion:)` method takes a closure that returns a promotion
piece kind. This allows for the app to prompt the user for a promotion piece or
perform any other operations before choosing a promotion piece kind.
```swift
try game.execute(move: move) {
...
return .queen
}
```
The closure is only executed if the move is a pawn promotion. An error is thrown
if the promotion piece kind cannot promote a pawn, such as with a king or pawn.
A piece kind can also be given without a closure. The default is a queen.
```swift
try game.execute(move: move, promotion: .queen)
```
### Pretty Printing
The `Board` and `Bitboard` types both have an `ascii` property that can be used
to print a visual board.
```swift
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 Notation
The `Game.Position` and `Board` types can both generate a FEN string.
```swift
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
```
They can also be initialized from a FEN string.
```swift
assert(Board(fen: game.board.fen()) == game.board)
assert(Game.Position(fen: game.position.fen()) == game.position)
```
### Iterating Through a Board
The `Board` type conforms to `Sequence`, making iterating through its spaces
seamless.
```swift
for space in Board() {
if let piece = space.piece {
print("\(piece) at \(space.square)")
}
}
```
### Squares to Moves
`Sequence` and `Square` have two methods that return an array of moves that go
from/to `self` to/from the parameter.
```swift
[.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 Usage
#### Board Quick Look
`Board` conforms to the `CustomPlaygroundDisplayConvertible` protocol.
![Playground quick look](https://raw.githubusercontent.com/SuperGeroy/Sage/assets/BoardPlaygroundView.png)
## To-Do
- [ ] SwiftUI Views (In-Progress)
- [ ] UCI Chess Engine Support
- [ ] SVG Resources
- Move Handling
- [ ] Enhance PGN Parsing
- [ ] Comprehensive PGN Support
- [ ] Support for different lines
- [ ] GameplayKit Support
### Possible Misc Enhancements
- Integrated Lichess Client (?)
- Player Database (?)
## License
Original Notice:
> Sage and its modifications are published under [version 2.0 of the Apache License](https://www.apache.org/licenses/LICENSE-2.0).
|