Bitboard to titboard ternary bitboard conversion
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A normal bitboard can only store two states per square: bit set or bit clear. A ternary board representation needs three states, such as empty, black, and white, so the first thing to understand is that a single bitboard does not contain enough information by itself. You usually convert from two related bitboards into a per-square ternary representation.
Start With a Clear State Mapping
Suppose each square may be in one of three states:
- '
0for empty' - '
1for player A' - '
2for player B'
A common binary representation is two 64-bit integers:
- one bitboard for player A occupancy
- one bitboard for player B occupancy
That is enough information to derive a ternary value per square. What you cannot do is convert a single occupancy bitboard into a ternary board unless some second source tells you which occupied squares belong to which state.
Convert Two Bitboards Into Ternary Cells
The simplest conversion is to build an array of 64 trits, one per board square.
This representation is easy to debug and easy to feed into evaluation code. It is not the most compact possible format, but it makes the conversion logic obvious.
Pack Ternary Values Only If You Really Need To
If the goal is compression, you can pack trits into bytes or larger integers. Five trits fit inside one byte because 3^5 is 243, which is less than 256. That gives a denser representation than storing one full byte per square.
That second step is optional. Many engines keep the original bitboards for move generation and use ternary conversion only for serialization, hashing, or machine-learning features.
Decide Why You Want a Ternary Form
The right representation depends on the operation:
- bitboards are excellent for fast bitwise move generation
- ternary cells are easier for generic board inspection or export
- packed trits are useful when compact storage matters
If your engine spends most of its time generating attacks or legal moves, converting everything into ternary form can slow down the hot path. In that case, derive ternary values only when another subsystem truly needs them.
Validate Before Converting
The biggest correctness rule is that the source bitboards must not overlap. If the same square is set in both bitboards, the ternary result is undefined because one square cannot simultaneously be in two non-empty states.
It is also worth agreeing on square ordering up front. Some code uses least-significant bit as the first square, while other code maps bits by rank and file differently. Two correct-looking conversion routines can disagree completely if they assume different square numbering.
Common Pitfalls
- Trying to derive three states from one bitboard with no extra metadata.
- Forgetting to reject overlapping source bitboards.
- Mixing up square numbering conventions during conversion.
- Packing trits too early and making debugging harder than necessary.
- Replacing fast bitboard logic with ternary arrays in performance-critical code.
Summary
- A single binary bitboard is not enough to represent a three-state board.
- The usual conversion starts from two occupancy bitboards and maps each square to
0,1, or2. - An array of trits is the simplest and safest ternary representation.
- Packed ternary storage is possible, but it is a separate optimization step.
- Keep bitboards for fast engine logic and convert only where ternary data is actually useful.

