Overview
The transform module provides functions for transforming chess positions through mirroring, rotating, and shifting operations. These transformations work on both SquareSet bitboards and complete Board or Setup positions.
All transformation functions work on SquareSet bitboards and return a new transformed SquareSet.
Flip Vertical
flipVertical(s: SquareSet): SquareSet
Flips the board vertically (mirrors across the horizontal center). Rank 1 becomes rank 8, rank 2 becomes rank 7, etc.
import { flipVertical } from 'chessops/transform';
import { SquareSet } from 'chessops/squareSet';
const whiteBackrank = SquareSet.backrank('white');
const flipped = flipVertical(whiteBackrank);
// Now represents rank 8 (black's backrank)
Implementation: Uses the bswap64() bitboard operation (byte swap).
export const flipVertical = (s: SquareSet): SquareSet => s.bswap64();
Flip Horizontal
flipHorizontal(s: SquareSet): SquareSet
Flips the board horizontally (mirrors across the vertical center). A-file becomes h-file, b-file becomes g-file, etc.
import { flipHorizontal } from 'chessops/transform';
const aFile = SquareSet.fromFile(0);
const flipped = flipHorizontal(aFile);
// Now represents h-file
Implementation: Uses bitwise operations to swap bits within each rank:
export const flipHorizontal = (s: SquareSet): SquareSet => {
const k1 = new SquareSet(0x55555555, 0x55555555);
const k2 = new SquareSet(0x33333333, 0x33333333);
const k4 = new SquareSet(0x0f0f0f0f, 0x0f0f0f0f);
s = s.shr64(1).intersect(k1).union(s.intersect(k1).shl64(1));
s = s.shr64(2).intersect(k2).union(s.intersect(k2).shl64(2));
s = s.shr64(4).intersect(k4).union(s.intersect(k4).shl64(4));
return s;
};
This performs a series of bit swaps: first swapping adjacent bits, then pairs of bits, then nibbles.
Flip Diagonal
flipDiagonal(s: SquareSet): SquareSet
Flips the board along the a1-h8 diagonal. This transposes the board: files become ranks and ranks become files.
import { flipDiagonal } from 'chessops/transform';
const rank1 = SquareSet.fromRank(0);
const flipped = flipDiagonal(rank1);
// Now represents a-file
Implementation: Uses delta-swap algorithm for diagonal transposition:
export const flipDiagonal = (s: SquareSet): SquareSet => {
let t = s.xor(s.shl64(28)).intersect(new SquareSet(0, 0x0f0f0f0f));
s = s.xor(t.xor(t.shr64(28)));
t = s.xor(s.shl64(14)).intersect(new SquareSet(0x33330000, 0x33330000));
s = s.xor(t.xor(t.shr64(14)));
t = s.xor(s.shl64(7)).intersect(new SquareSet(0x55005500, 0x55005500));
s = s.xor(t.xor(t.shr64(7)));
return s;
};
Rotate 180°
rotate180(s: SquareSet): SquareSet
Rotates the board 180 degrees. Equivalent to flipping both vertically and horizontally.
import { rotate180 } from 'chessops/transform';
const bottomLeft = SquareSet.fromSquare(0); // a1
const rotated = rotate180(bottomLeft);
// Now represents h8 (square 63)
Implementation: Uses reverse bit order operation:
export const rotate180 = (s: SquareSet): SquareSet => s.rbit64();
rotate180() is particularly useful for converting between perspectives in chess GUIs or for symmetry analysis.
Directional Shifts
Shift operations move pieces in a specific direction, wrapping around board edges.
Shift Left
shiftLeft(squares: SquareSet): SquareSet
Shifts all squares one file to the left. Squares on the a-file wrap to the h-file.
import { shiftLeft } from 'chessops/transform';
const e4 = SquareSet.fromSquare(makeSquare('e4'));
const shifted = shiftLeft(e4);
// Now represents d4
Implementation:
export const shiftLeft = (squares: SquareSet): SquareSet =>
squares
.diff(SquareSet.fromFile(0)) // Remove a-file
.shr64(1) // Shift right by 1
.union(squares.intersect(SquareSet.fromFile(0)).shl64(7)); // Wrap a-file to h-file
Shift Right
shiftRight(squares: SquareSet): SquareSet
Shifts all squares one file to the right. Squares on the h-file wrap to the a-file.
import { shiftRight } from 'chessops/transform';
const d4 = SquareSet.fromSquare(makeSquare('d4'));
const shifted = shiftRight(d4);
// Now represents e4
Shift Up
shiftUp(squares: SquareSet): SquareSet
Shifts all squares one rank up. Squares on rank 8 wrap to rank 1.
import { shiftUp } from 'chessops/transform';
const e4 = SquareSet.fromSquare(makeSquare('e4'));
const shifted = shiftUp(e4);
// Now represents e5
Shift Down
shiftDown(squares: SquareSet): SquareSet
Shifts all squares one rank down. Squares on rank 1 wrap to rank 8.
import { shiftDown } from 'chessops/transform';
const e5 = SquareSet.fromSquare(makeSquare('e5'));
const shifted = shiftDown(e5);
// Now represents e4
Shift functions wrap around the board edges. This behavior is useful for certain chess variants or pattern analysis, but may not be suitable for standard move generation.
Transform complete board positions while preserving piece types and colors.
transformBoard(
board: Board,
f: (s: SquareSet) => SquareSet
): Board
Applies a SquareSet transformation function to all pieces on the board.
import { transformBoard, flipVertical } from 'chessops/transform';
import { Board } from 'chessops/board';
const board = Board.default();
const flipped = transformBoard(board, flipVertical);
// Board is now mirrored vertically
Implementation:
export const transformBoard = (
board: Board,
f: (s: SquareSet) => SquareSet,
): Board => {
const b = Board.empty();
b.occupied = f(board.occupied);
b.promoted = f(board.promoted);
for (const color of COLORS) b[color] = f(board[color]);
for (const role of ROLES) b[role] = f(board[role]);
return b;
};
This transforms:
- All occupied squares
- Promoted piece positions
- Piece positions by color (white/black)
- Piece positions by role (pawn/knight/bishop/rook/queen/king)
transformSetup(
setup: Setup,
f: (s: SquareSet) => SquareSet
): Setup
Transforms a complete position setup, including castling rights and en passant squares.
import { transformSetup, flipVertical } from 'chessops/transform';
import { parseFen } from 'chessops/fen';
const setup = parseFen('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1').unwrap();
const flipped = transformSetup(setup, flipVertical);
// Entire position is flipped, preserving game state
Key features:
- Transforms the board using
transformBoard()
- Preserves pockets (for Crazyhouse variant)
- Keeps turn, halfmove, and fullmove counters unchanged
- Transforms castling rights appropriately
- Transforms en passant square if present
- Preserves remaining checks (for Three-Check variant)
Use Cases
View from Black’s Perspective
import { transformSetup, rotate180 } from 'chessops/transform';
function viewFromBlack(setup: Setup): Setup {
return transformSetup(setup, rotate180);
}
Symmetry Analysis
import { flipHorizontal, flipVertical } from 'chessops/transform';
function isSymmetric(board: Board): boolean {
const horizontalFlip = transformBoard(board, flipHorizontal);
const verticalFlip = transformBoard(board, flipVertical);
return board.occupied.equals(horizontalFlip.occupied) ||
board.occupied.equals(verticalFlip.occupied);
}
Pattern Matching
Find patterns regardless of board orientation:
import { transformBoard, flipVertical, flipHorizontal, rotate180 } from 'chessops/transform';
function findPattern(board: Board, pattern: Board): boolean {
const transformations = [
(b: Board) => b,
(b: Board) => transformBoard(b, flipVertical),
(b: Board) => transformBoard(b, flipHorizontal),
(b: Board) => transformBoard(b, rotate180),
];
for (const transform of transformations) {
const transformed = transform(board);
if (matchesPattern(transformed, pattern)) {
return true;
}
}
return false;
}
Chess960 Analysis
Normalize Chess960 positions for comparison:
import { transformSetup, flipHorizontal } from 'chessops/transform';
function normalizeChess960(setup: Setup): Setup {
// If king is on queenside, flip to kingside
const kingSquare = setup.board.kingOf('white');
if (kingSquare && squareFile(kingSquare) < 4) {
return transformSetup(setup, flipHorizontal);
}
return setup;
}
Combine multiple transformations to create complex board manipulations. For example, flipVertical(flipHorizontal(s)) is equivalent to rotate180(s).
- All transformations are pure functions (no mutations)
- SquareSet operations are constant-time bitwise operations
- Board transformations iterate over all piece types and colors
- Transformations create new objects rather than modifying existing ones
For repeated transformations, consider caching results. SquareSets are immutable, making them safe to cache.