diff options
Diffstat (limited to 'src/eval.c')
| -rwxr-xr-x | src/eval.c | 229 |
1 files changed, 101 insertions, 128 deletions
@@ -4803,14 +4803,11 @@ Return value: **/ { - ULONG uDefer[2][2]; - COOR cDefer[2][2][10]; POSITION *pos = &(ctx->sPosition); SCORE iScoreForSideToMove; SCORE iAlphaMargin, iBetaMargin; PAWN_HASH_ENTRY *pHash; COOR c; - PIECE p; ULONG u; ULONG uColor; BITBOARD bb; @@ -5054,131 +5051,111 @@ Return value: // // Evaluate individual pieces. // + // board_representation/EVAL.md section 0/2: replaces the old + // cNonPawns[color][1..N] walk + per-piece mailbox lookup + p&0x4/ + // IS_KNIGHT branch dispatch (a hard-to-predict branch per piece, + // on top of a redundant mailbox read the callee already redoes + // for its own ASSERT) with a direct per-type location-bitboard + // walk. pos->bbPieces[color][PIECE_TYPE] already exists, + // incrementally maintained by move.c, and was simply unused by + // Eval() until now -- no new infrastructure, purely a consumer + // change. Also retires the cDefer/uDefer "remember the rooks and + // queens for later" bookkeeping entirely: since each type is now + // its own direct bitboard walk, "evaluate rooks after minors" is + // just "do the rook-bitboard walk after the minor-bitboard walks" + // -- nothing to defer. + // + // Phase order preserved exactly as before (side-to-move's minors, + // then the other side's minors, then rooks both colors, then + // queens both colors) -- that ordering is load-bearing for + // bvAttacks accumulation (each piece's mobility/danger depends on + // attack bits already written by earlier-evaluated pieces this + // same Eval() call). Knight-vs-bishop order *within* the same + // color/phase, and encounter order within a single type's own + // bitboard walk, were never meaningful before (cNonPawns' order + // is arbitrary swap-with-last-on-removal, not stable) and stay + // that way -- EVAL_TERM's plain score accumulation doesn't care. + // pos->uMinorsAtHome[BLACK] = pos->uMinorsAtHome[WHITE] = 0; - uDefer[BLACK][0] = uDefer[BLACK][1] = - uDefer[WHITE][0] = uDefer[WHITE][1] = 0; uColor = pos->uToMove; - for (u = 1; // skips the king - u < pos->uNonPawnCount[uColor][0]; - u++) + bb = pos->bbPieces[uColor][KNIGHT]; + while (bb) { - c = pos->cNonPawns[uColor][u]; - ASSERT(IS_ON_BOARD(c)); - p = pos->rgSquare[c].pPiece; - ASSERT(IS_VALID_PIECE(p)); - ASSERT(GET_COLOR(p) == uColor); - ASSERT(!IS_PAWN(p) && !IS_KING(p)); - - if (p & 0x4) - { - ASSERT(IS_BISHOP(p) || IS_KNIGHT(p)); - - // - // Note: The side on move's pieces of value X are - // evaluated and have their mobility counted and added to - // the attack table before the other side's pieces. Also, - // we do not care if this piece is in danger b/c we will - // find out later on in EvalLookForDanger anyway. - // - if (IS_KNIGHT(p)) - { - TIMED_EVAL_CALL(ctx, u64CyclesEvalKnight, - _EvalKnight(pos, c, pHash)); - } - else - { - TIMED_EVAL_CALL(ctx, u64CyclesEvalBishop, - _EvalBishop(pos, c, pHash)); - } + u = FastFirstBit(bb) - 1; + bb &= (bb - 1); + c = BIT_NUMBER_TO_COOR(u); + TIMED_EVAL_CALL(ctx, u64CyclesEvalKnight, + _EvalKnight(pos, c, pHash)); #ifdef EVAL_DUMP - Trace("After %s:\n%d\t\t%d\n", PieceAbbrev(p), - pos->iScore[WHITE], pos->iScore[BLACK]); + Trace("After N:\n%d\t\t%d\n", pos->iScore[WHITE], pos->iScore[BLACK]); +#endif + } + bb = pos->bbPieces[uColor][BISHOP]; + while (bb) + { + u = FastFirstBit(bb) - 1; + bb &= (bb - 1); + c = BIT_NUMBER_TO_COOR(u); + TIMED_EVAL_CALL(ctx, u64CyclesEvalBishop, + _EvalBishop(pos, c, pHash)); +#ifdef EVAL_DUMP + Trace("After B:\n%d\t\t%d\n", pos->iScore[WHITE], pos->iScore[BLACK]); #endif - } - else - { - ASSERT(IS_ROOK(p) || IS_QUEEN(p)); - cDefer[uColor][IS_QUEEN(p)][uDefer[uColor][IS_QUEEN(p)]++] = c; - } } uColor = FLIP(uColor); ASSERT(uColor != pos->uToMove); - for (u = 1; - u < pos->uNonPawnCount[uColor][0]; - u++) + bb = pos->bbPieces[uColor][KNIGHT]; + while (bb) { - c = pos->cNonPawns[uColor][u]; - ASSERT(IS_ON_BOARD(c)); - p = pos->rgSquare[c].pPiece; - ASSERT(IS_VALID_PIECE(p)); - ASSERT(GET_COLOR(p) == uColor); - ASSERT(!IS_PAWN(p) && !IS_KING(p)); - if (p & 0x4) - { - // - // This time we are evaluating a piece from the side not - // on move. We will not go back later and look at this - // piece again so if it's in danger then record it. The - // drawback, of course, is that danger is only detected if - // a piece is attacked by an enemy of lesser value! - // - if (IS_KNIGHT(p)) - { - TIMED_EVAL_CALL(ctx, u64CyclesEvalKnight, - _EvalKnight(pos, c, pHash)); - } - else - { - TIMED_EVAL_CALL(ctx, u64CyclesEvalBishop, - _EvalBishop(pos, c, pHash)); - } + u = FastFirstBit(bb) - 1; + bb &= (bb - 1); + c = BIT_NUMBER_TO_COOR(u); + TIMED_EVAL_CALL(ctx, u64CyclesEvalKnight, + _EvalKnight(pos, c, pHash)); #ifdef EVAL_DUMP - Trace("After %s:\n%d\t\t%d\n", PieceAbbrev(p), - pos->iScore[WHITE], pos->iScore[BLACK]); + Trace("After N:\n%d\t\t%d\n", pos->iScore[WHITE], pos->iScore[BLACK]); +#endif + } + bb = pos->bbPieces[uColor][BISHOP]; + while (bb) + { + u = FastFirstBit(bb) - 1; + bb &= (bb - 1); + c = BIT_NUMBER_TO_COOR(u); + TIMED_EVAL_CALL(ctx, u64CyclesEvalBishop, + _EvalBishop(pos, c, pHash)); +#ifdef EVAL_DUMP + Trace("After B:\n%d\t\t%d\n", pos->iScore[WHITE], pos->iScore[BLACK]); #endif - } - else - { - ASSERT(IS_ROOK(p) || IS_QUEEN(p)); - cDefer[uColor][IS_QUEEN(p)][uDefer[uColor][IS_QUEEN(p)]++] = c; - } } // // Evaluate any rook(s) for side on move then for side not on move. // uColor = FLIP(uColor); - for (u = 0; - u < uDefer[uColor][0]; - u++) + bb = pos->bbPieces[uColor][ROOK]; + while (bb) { - c = cDefer[uColor][0][u]; - ASSERT(IS_ON_BOARD(c)); - ASSERT(IS_ROOK(pos->rgSquare[c].pPiece)); - ASSERT(GET_COLOR(pos->rgSquare[c].pPiece) == uColor); + u = FastFirstBit(bb) - 1; + bb &= (bb - 1); + c = BIT_NUMBER_TO_COOR(u); TIMED_EVAL_CALL(ctx, u64CyclesEvalRook, _EvalRook(pos, c, pHash)); #ifdef EVAL_DUMP - p = BLACK_ROOK | uColor; - Trace("After %s:\n%d\t\t%d\n", PieceAbbrev(p), - pos->iScore[WHITE], pos->iScore[BLACK]); + Trace("After R:\n%d\t\t%d\n", pos->iScore[WHITE], pos->iScore[BLACK]); #endif } uColor = FLIP(uColor); - for (u = 0; - u < uDefer[uColor][0]; - u++) + bb = pos->bbPieces[uColor][ROOK]; + while (bb) { - c = cDefer[uColor][0][u]; - ASSERT(IS_ON_BOARD(c)); - ASSERT(IS_ROOK(pos->rgSquare[c].pPiece)); - ASSERT(GET_COLOR(pos->rgSquare[c].pPiece) == uColor); + u = FastFirstBit(bb) - 1; + bb &= (bb - 1); + c = BIT_NUMBER_TO_COOR(u); TIMED_EVAL_CALL(ctx, u64CyclesEvalRook, _EvalRook(pos, c, pHash)); #ifdef EVAL_DUMP - p = BLACK_ROOK | uColor; - Trace("After %s:\n%d\t\t%d\n", PieceAbbrev(p), - pos->iScore[WHITE], pos->iScore[BLACK]); + Trace("After R:\n%d\t\t%d\n", pos->iScore[WHITE], pos->iScore[BLACK]); #endif } @@ -5186,36 +5163,28 @@ Return value: // Evaluate any queen(s) for side on move then for side not on move. // uColor = FLIP(uColor); - for (u = 0; - u < uDefer[uColor][1]; - u++) + bb = pos->bbPieces[uColor][QUEEN]; + while (bb) { - c = cDefer[uColor][1][u]; - ASSERT(IS_ON_BOARD(c)); - ASSERT(IS_QUEEN(pos->rgSquare[c].pPiece)); - ASSERT(GET_COLOR(pos->rgSquare[c].pPiece) == uColor); + u = FastFirstBit(bb) - 1; + bb &= (bb - 1); + c = BIT_NUMBER_TO_COOR(u); TIMED_EVAL_CALL(ctx, u64CyclesEvalQueen, _EvalQueen(pos, c, pHash)); #ifdef EVAL_DUMP - p = BLACK_ROOK | uColor; - Trace("After %s:\n%d\t\t%d\n", PieceAbbrev(p), - pos->iScore[WHITE], pos->iScore[BLACK]); + Trace("After Q:\n%d\t\t%d\n", pos->iScore[WHITE], pos->iScore[BLACK]); #endif } uColor = FLIP(uColor); - for (u = 0; - u < uDefer[uColor][1]; - u++) + bb = pos->bbPieces[uColor][QUEEN]; + while (bb) { - c = cDefer[uColor][1][u]; - ASSERT(IS_ON_BOARD(c)); - ASSERT(IS_QUEEN(pos->rgSquare[c].pPiece)); - ASSERT(GET_COLOR(pos->rgSquare[c].pPiece) == uColor); + u = FastFirstBit(bb) - 1; + bb &= (bb - 1); + c = BIT_NUMBER_TO_COOR(u); TIMED_EVAL_CALL(ctx, u64CyclesEvalQueen, _EvalQueen(pos, c, pHash)); #ifdef EVAL_DUMP - p = BLACK_ROOK | uColor; - Trace("After %s:\n%d\t\t%d\n", PieceAbbrev(p), - pos->iScore[WHITE], pos->iScore[BLACK]); + Trace("After Q:\n%d\t\t%d\n", pos->iScore[WHITE], pos->iScore[BLACK]); #endif } @@ -5225,10 +5194,12 @@ Return value: c = pos->cNonPawns[BLACK][0]; #ifdef DEBUG ASSERT(IS_ON_BOARD(c)); - p = pos->rgSquare[c].pPiece; - ASSERT(IS_VALID_PIECE(p)); - ASSERT(GET_COLOR(p) == BLACK); - ASSERT(IS_KING(p)); + { + PIECE pDebugKing = pos->rgSquare[c].pPiece; + ASSERT(IS_VALID_PIECE(pDebugKing)); + ASSERT(GET_COLOR(pDebugKing) == BLACK); + ASSERT(IS_KING(pDebugKing)); + } #endif TIMED_EVAL_CALL(ctx, u64CyclesEvalKing, _EvalKing(pos, c, pHash)); ctx->sPlyInfo[ctx->uPly].iKingScore[BLACK] = pos->iTempScore; @@ -5239,10 +5210,12 @@ Return value: c = pos->cNonPawns[WHITE][0]; #ifdef DEBUG ASSERT(IS_ON_BOARD(c)); - p = pos->rgSquare[c].pPiece; - ASSERT(IS_VALID_PIECE(p)); - ASSERT(GET_COLOR(p) == WHITE); - ASSERT(IS_KING(p)); + { + PIECE pDebugKing = pos->rgSquare[c].pPiece; + ASSERT(IS_VALID_PIECE(pDebugKing)); + ASSERT(GET_COLOR(pDebugKing) == WHITE); + ASSERT(IS_KING(pDebugKing)); + } #endif TIMED_EVAL_CALL(ctx, u64CyclesEvalKing, _EvalKing(pos, c, pHash)); ctx->sPlyInfo[ctx->uPly].iKingScore[WHITE] = pos->iTempScore; |
