Sage is a cross-platform chess library for Swift.
Features
- Chess game management
- Chess board structuring
- Move generation / validation
- En passant and castling
- Pawn promotions
- FEN for games and boards
- Documentation
Installation
Compatibility
- Platforms:
- macOS 10.9+
- iOS 8.0+
- watchOS 2.0+
- tvOS 9.0+
- Linux
- Xcode 7.3 and 8.0
- Swift 2.2 and 3.0
Install Using Swift Package Manager
The Swift Package Manager is a decentralized dependency manager for Swift.
Add the project to your
Package.swift.import PackageDescription let package = Package( name: "MyAwesomeProject", dependencies: [ .Package(url: "https://github.com/nvzqz/Sage.git", majorVersion: 1) ] )Import the Sage module.
Install Using CocoaPods
CocoaPods is a centralized dependency manager for Objective-C and Swift. Go here to learn more.
Add the project to your Podfile.
use_frameworks! pod 'Sage', '~> 1.0.0'Run
pod installand open the.xcworkspacefile to launch Xcode.Import the Sage framework.
Install Using Carthage
Carthage is a decentralized dependency manager for Objective-C and Swift.
Add the project to your Cartfile.
github "nvzqz/Sage"Run
carthage updateand follow the additional steps in order to add Sage to your project.Import the Sage framework.
Usage
Game Management
Running a chess game can be as simple as setting up a loop.
import Sage
let game = Game()
while !game.isFinished {
let move = ...
try game.execute(move: move)
}
Move Generation
Sage 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
Sage 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. This allows for the app to prompt the user for a promotion piece or
perform any other operations before choosing a promotion piece.
try game.execute(move: move) {
...
return .queen(game.playerTurn)
}
The closure is only executed if the move is a pawn promotion. An error is thrown
if the promotion piece is the wrong color or cannot promote a pawn, such as with
a king or pawn.
A piece can be given without a closure. The default promotion piece is a queen.
try game.execute(move: move, promotion: .queen(game.playerTurn))
Pretty Printing
The Board and Bitboard types both have an ascii property that can be used
to print a visual board.
let board = Board()
print(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
print(board.bitboard().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.
let game = Game()
print(game.position.fen())
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
print(game.board.fen())
// rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR
They can also be initialized from a FEN string.
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.
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.
print([.a1, .h3, .b5].moves(from: .b4))
// [b4 >>> a1, b4 >>> h3, b4 >>> b5]
print([.c3, .d2, .f1].moves(to: .a6))
// [c3 >>> a6, d2 >>> a6, f1 >>> a6]
print(Square.d4.moves(from: [.c2, .f8, .h2]))
// [c2 >>> d4, f8 >>> d4, h2 >>> d4]
print(Square.a4.moves(to: [.c3, .d4, .f6]))
// [a4 >>> c3, a4 >>> d4, a4 >>> f6]
Playground Quick Look
Board conforms to the CustomPlaygroundQuickLookable protocol.
License
Sage is published under version 2.0 of the Apache License.
