Skip to content

Add support for very large boards and guard Omega variant#14

Closed
Belzedar94 wants to merge 4 commits intomasterfrom
codex/implement-256-bit-bitboard-for-16x16-recsi3
Closed

Add support for very large boards and guard Omega variant#14
Belzedar94 wants to merge 4 commits intomasterfrom
codex/implement-256-bit-bitboard-for-16x16-recsi3

Conversation

@Belzedar94
Copy link
Copy Markdown
Owner

Summary

  • add a 256-bit Bitboard implementation and board geometry constants to enable VERY_LARGE_BOARDS builds up to 16×16
  • allocate file/rank masks and rider attack tables at runtime for very large boards, switching to on-the-fly sliding attacks when tables would explode in size
  • update Omega chess to the 12×12 layout and register it only for VERY_LARGE_BOARDS builds, along with refreshed Python regression data and help text for the new build targets

Testing

  • make build -j2 ARCH=x86-64
  • make build -j2 ARCH=x86-64 verylargeboards=yes
  • python3 test.py (fails with a segmentation fault when importing pyffish built with VERY_LARGE_BOARDS)

https://chatgpt.com/codex/tasks/task_e_68cc5e69d3348322beb185dbec93be00

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex Review: Here are some suggestions.

if (isdigit(token))
{
#ifdef LARGEBOARDS
if (isdigit(ss.peek()))
{
sq += 10 * (token - '0') * EAST;
ss >> token;
}
#endif
sq += (token - '0') * EAST; // Advance the given number of files
}
else if (token == '/')
{
sq = SQ_A1 + --r * NORTH;
if (!is_ok(sq))
break;
}
// Stop before pieces in hand
else if (token == '[')
break;
// Ignore pieces outside the board and wait for next / or [ to return to a valid state
else if (!is_ok(sq) || file_of(sq) > max_file() || rank_of(sq) > r)
continue;
// Wall square
else if (token == '*')
{
st->wallSquares |= sq;
byTypeBB[ALL_PIECES] |= sq;
++sq;
}
else if ((idx = piece_to_char().find(token)) != string::npos || (idx = piece_to_char_synonyms().find(token)) != string::npos)
{
if (ss.peek() == '~')
ss >> token;
put_piece(Piece(idx), sq, token == '~');
++sq;
}
// Promoted shogi pieces
else if (token == '+' && (idx = piece_to_char().find(ss.peek())) != string::npos && promoted_piece_type(type_of(Piece(idx))))
{
ss >> token;
put_piece(make_piece(color_of(Piece(idx)), promoted_piece_type(type_of(Piece(idx)))), sq, true, Piece(idx));
++sq;
}
}
// Pieces in hand
if (!isspace(token))
while ((ss >> token) && !isspace(token))
{
if (token == ']')
continue;
else if ((idx = piece_to_char().find(token)) != string::npos)
add_to_hand(Piece(idx));
}
// 2. Active color
ss >> token;
sideToMove = (token != (sfen ? 'w' : 'b') ? WHITE : BLACK); // Invert colors for SFEN
ss >> token;
// 3-4. Skip parsing castling and en passant flags if not present
st->epSquares = 0;
st->castlingKingSquare[WHITE] = st->castlingKingSquare[BLACK] = SQ_NONE;
if (!isdigit(ss.peek()) && !sfen)
{
// 3. Castling availability. Compatible with 3 standards: Normal FEN standard,
// Shredder-FEN that uses the letters of the columns on which the rooks began
// the game instead of KQkq and also X-FEN standard that, in case of Chess960,
// if an inner rook is associated with the castling right, the castling tag is
// replaced by the file letter of the involved rook, as for the Shredder-FEN.
while ((ss >> token) && !isspace(token))
{
Square rsq;
Color c = islower(token) ? BLACK : WHITE;
token = char(toupper(token));
if (castling_enabled() && token == 'K')
for (rsq = make_square(var->castlingRookKingsideFile, castling_rank(c)); (!(castling_rook_pieces(c) & type_of(piece_on(rsq))) || color_of(piece_on(rsq)) != c) && file_of(rsq) > FILE_A; --rsq) {}
else if (castling_enabled() && token == 'Q')
for (rsq = make_square(var->castlingRookQueensideFile, castling_rank(c)); (!(castling_rook_pieces(c) & type_of(piece_on(rsq))) || color_of(piece_on(rsq)) != c) && file_of(rsq) < max_file(); ++rsq) {}
else if (token >= 'A' && token <= 'A' + max_file())
rsq = make_square(File(token - 'A'), castling_rank(c));
else
continue;
// Determine castling "king" position
if (castling_enabled() && st->castlingKingSquare[c] == SQ_NONE)
{
Bitboard castlingKings = pieces(c, castling_king_piece(c)) & rank_bb(castling_rank(c));
// Ambiguity resolution for 960 variants with more than one "king"
// e.g., EAH means that an e-file king can castle with a- and h-file rooks
st->castlingKingSquare[c] = isChess960 && piece_on(rsq) == make_piece(c, castling_king_piece(c)) ? rsq
: castlingKings && (!more_than_one(castlingKings) || isChess960) ? lsb(castlingKings)
: make_square(castling_king_file(), castling_rank(c));
// Skip invalid castling rights
if (!(castlingKings & st->castlingKingSquare[c]))
st->castlingKingSquare[c] = SQ_NONE;
}
// Set gates (and skip castling rights)
if (gating())
{
// Only add gates for occupied squares
if (pieces(c) & rsq)
st->gatesBB[c] |= rsq;
if ((token == 'K' || token == 'Q') && st->castlingKingSquare[c] != SQ_NONE)
st->gatesBB[c] |= st->castlingKingSquare[c];
// Do not set castling rights for gates unless there are no pieces in hand,
// which means that the file is referring to a chess960 castling right.
else if (!seirawan_gating() || count_in_hand(c, ALL_PIECES) > 0 || captures_to_hand())
continue;
}
// Only add castling right if both king and rook are on expected squares
if ( castling_enabled()
&& st->castlingKingSquare[c] != SQ_NONE
&& (castling_rook_pieces(c) & type_of(piece_on(rsq))) && color_of(piece_on(rsq)) == c)
set_castling_right(c, rsq);
}
// Set castling rights for 960 gating variants
if (gating() && castling_enabled())
for (Color c : {WHITE, BLACK})
if ((gates(c) & pieces(castling_king_piece(c))) && !castling_rights(c) && (!seirawan_gating() || count_in_hand(c, ALL_PIECES) > 0 || captures_to_hand()))
{
Bitboard castling_rooks = gates(c) & pieces(c);
while (castling_rooks)
{
Square s = pop_lsb(castling_rooks);
if (castling_rook_pieces(c) & type_of(piece_on(s)))
set_castling_right(c, s);
}
}
// counting limit
if (counting_rule() && isdigit(ss.peek()))
ss >> st->countingLimit;
// 4. En passant square.
// Ignore if square is invalid or not on side to move relative rank 6.
else
while ( ((ss >> col) && (col >= 'a' && col <= 'a' + max_file()))
&& ((ss >> row) && (row >= '1' && row <= '1' + max_rank())))
{
Square epSquare = make_square(File(col - 'a'), Rank(row - '1'));
#ifdef LARGEBOARDS
// Consider different rank numbering in CECP
if (max_rank() == RANK_10 && CurrentProtocol == XBOARD)

[P0] Parse 12×12 FEN rows incorrectly in VERY_LARGE builds

The FEN parser still treats multi‑digit empty square counts and rank coordinates only when LARGEBOARDS is defined. In a VERY_LARGE_BOARDS build the code at Position::set never reads the second digit of tokens like 10, so the new 12×12 Omega start position is misinterpreted and sq advances by one square instead of ten. The same guard around the en‑passant loop reads only a single rank character. On startup the engine parses Omega’s FEN and writes past the board arrays, which is why the VERY_LARGE_BOARDS binary crashes immediately. These blocks should include VERY_LARGE_BOARDS so that two‑digit ranks/files are parsed correctly for 16×16 style boards.


Reply with @codex fix comments to fix any unresolved comments.

About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you open a pull request for review, mark a draft as ready, or comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex fix this CI failure" or "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant