Skip to content

Commit

Permalink
rewrote collinearN code. other connect optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
RainRat committed May 21, 2024
1 parent dba5dd3 commit e0ac150
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/evaluate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1281,7 +1281,7 @@ namespace {
}

// Connect-n
if (pos.connect_n() > 0)
if (pos.connect_n() > 0 && (pos.variant()->connectValue != VALUE_DRAW))
{
//Calculate eligible pieces for connection once.
//Still consider all opponent pieces as blocking.
Expand Down
58 changes: 34 additions & 24 deletions src/position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2801,7 +2801,7 @@ bool Position::is_immediate_game_end(Value& result, int ply) const {
connectPieces &= pieces(~sideToMove);

// Connect-n
if (connect_n() > 0)
if ((connect_n() > 0) && (popcount(connectPieces) >= connect_n()))
{
Bitboard b;

Expand Down Expand Up @@ -2843,8 +2843,8 @@ bool Position::is_immediate_game_end(Value& result, int ply) const {
current |= newBitboard;
}
}
if (connect_nxn())

if ((connect_nxn()) && (popcount(connectPieces) >= connect_nxn() * connect_nxn()))
{
Bitboard connectors = connectPieces;
for (int i = 1; i < connect_nxn() && connectors; i++)
Expand All @@ -2858,27 +2858,37 @@ bool Position::is_immediate_game_end(Value& result, int ply) const {

// Collinear-n
if (collinear_n() > 0) {
Bitboard allPieces = connectPieces;
for (Direction d : var->connect_directions) {
Bitboard b = allPieces;
while (b) {
Square s = pop_lsb(b);

int total_count = 1; // Start with the current piece

// Check in both directions
for (int sign : {-1, 1}) {
Bitboard shifted = shift(sign * d, square_bb(s));
while (shifted) {
if (shifted & b) {
total_count++;
b &= ~shifted; // Remove this piece from further consideration
}
shifted = shift(sign * d, shifted);
}
}

if (total_count >= collinear_n()) {
Bitboard pieces = connectPieces;
while (pieces) {
if (popcount(pieces) < collinear_n()) {
break; // Early out to the next section
}
//Use pop_lsb to loop through the pieces. Then for each of the directions,
//use line_bb to calculate the entire row, column or diagonal that contains
//the piece and the shifted square, then use popcount to count the number
//of pieces on that line.
Square s = pop_lsb(pieces);
for (Direction d : var->connect_directions) {
Square shifted_square = s + d;


if (!is_ok(shifted_square)) continue; //This is totally fine.
//Pieces where the shift is outside the board will not be processed
//for that direction, but in order to be collinear with another piece,
//there would be another piece that counts it as part of its line.
//Even if say, all the pieces were on the EAST edge, it's the NORTH
//direction that would count them up.
//Only exception is that if collinearN was set to 1, and there was 1
//piece on the NORTH_EAST corner, it wouldn't count. Possible solutions:
//1. Ignore
//2. Tell user that collinearN=1 is silly, use flagPieces or connectN
//3. Special case here to check
//4. Quietly convert it to connectN=1


Bitboard line = line_bb(s, shifted_square);
int piece_count = popcount(line & connectPieces);
if (piece_count >= collinear_n()) {
result = convert_mate_value(-var->connectValue, ply);
return true;
}
Expand Down

0 comments on commit e0ac150

Please sign in to comment.