int MvvLva(POS *p, int move) { // Captures if (p->pc[Tsq(move)] != NO_PC) return TpOnSq(p, Tsq(move)) * 6 + 5 - TpOnSq(p, Fsq(move)); // Non-capturing promotions if (IsProm(move)) return PromType(move) - 5; return 5; }
void sManipulator::DoMove(sPosition *p, int move, UNDO *u) { int side = p->side; // moving side int fsq = Fsq(move); // start square int tsq = Tsq(move); // target square int ftp = TpOnSq(p, fsq); // moving piece int ttp = TpOnSq(p, tsq); // captured piece U64 bbMove = SqBb(fsq) | SqBb(tsq); // optimization from Stockfish // save data for undoing a move u->ttp = ttp; u->castleFlags = p->castleFlags; u->epSquare = p->epSquare; u->reversibleMoves = p->reversibleMoves; u->hashKey = p->hashKey; u->pawnKey = p->pawnKey; p->repetitionList[p->head++] = p->hashKey; // update reversible move counter (zeroing is done on captures and pawn moves) p->reversibleMoves++; p->hashKey ^= zobCastle[p->castleFlags]; p->castleFlags &= castleMask[fsq] & castleMask[tsq]; p->hashKey ^= zobCastle[p->castleFlags]; // clear en passant square if (p->epSquare != NO_SQ) { p->hashKey ^= zobEp[File(p->epSquare)]; p->epSquare = NO_SQ; } // move a piece from start square p->pc[fsq] = NO_PC; p->pc[tsq] = Pc(side, ftp); p->hashKey ^= zobPiece[Pc(side, ftp)][fsq] ^ zobPiece[Pc(side, ftp)][tsq]; if (ftp == P) { p->reversibleMoves = 0; p->pawnKey ^= zobPiece[Pc(side, ftp)][fsq] ^ zobPiece[Pc(side, ftp)][tsq]; } p->bbCl[side] ^= bbMove; p->bbTp[ftp] ^= bbMove; p->pstMg[side] += Data.pstMg[side][ftp][tsq] - Data.pstMg[side][ftp][fsq]; p->pstEg[side] += Data.pstEg[side][ftp][tsq] - Data.pstEg[side][ftp][fsq]; // on a king move update king location data if (ftp == K) p->kingSquare[side] = tsq; // capture if (ttp != NO_TP) { p->reversibleMoves = 0; p->hashKey ^= zobPiece[Pc(Opp(side), ttp)][tsq]; if (ttp == P) p->pawnKey ^= zobPiece[Pc(Opp(side), ttp)][tsq]; p->bbCl[Opp(side)] ^= SqBb(tsq); p->bbTp[ttp] ^= SqBb(tsq); p->pcCount[Opp(side)][ttp]--; p->pieceMat[Opp(side)] -= Data.matValue[ttp]; p->phase -= Data.phaseValue[ttp]; p->pstMg[Opp(side)] -= Data.pstMg[Opp(side)][ttp][tsq]; p->pstEg[Opp(side)] -= Data.pstEg[Opp(side)][ttp][tsq]; } switch (MoveType(move)) { case NORMAL: break; case CASTLE: if (tsq > fsq) { fsq += 3; tsq -= 1; } else { fsq -= 4; tsq += 1; } p->pc[fsq] = NO_PC; p->pc[tsq] = Pc(side, R); p->hashKey ^= zobPiece[Pc(side, R)][fsq] ^ zobPiece[Pc(side, R)][tsq]; p->bbCl[side] ^= SqBb(fsq) | SqBb(tsq); p->bbTp[R] ^= SqBb(fsq) | SqBb(tsq); p->pstMg[side] += Data.pstMg[side][R][tsq] - Data.pstMg[side][R][fsq]; p->pstEg[side] += Data.pstEg[side][R][tsq] - Data.pstEg[side][R][fsq]; break; case EP_CAP: tsq ^= 8; p->pc[tsq] = NO_PC; p->hashKey ^= zobPiece[Pc(Opp(side), P)][tsq]; p->pawnKey ^= zobPiece[Pc(Opp(side), P)][tsq]; p->bbCl[Opp(side)] ^= SqBb(tsq); p->bbTp[P] ^= SqBb(tsq); p->pcCount[Opp(side)][P]--; p->phase -= Data.phaseValue[P]; p->pstMg[Opp(side)] -= Data.pstMg[Opp(side)][P][tsq]; p->pstEg[Opp(side)] -= Data.pstEg[Opp(side)][P][tsq]; break; case EP_SET: tsq ^= 8; if (bbPawnAttacks[side][tsq] & bbPc(p, Opp(side), P)) { p->epSquare = tsq; p->hashKey ^= zobEp[File(tsq)]; } break; // promotion: (1) add promoted piece and add values associated with it case N_PROM: // (2) remove promoted pawn and substract values associated with it case B_PROM: case R_PROM: case Q_PROM: ftp = PromType(move); p->pc[tsq] = Pc(side, ftp); p->hashKey ^= zobPiece[Pc(side, P)][tsq] ^ zobPiece[Pc(side, ftp)][tsq]; p->pawnKey ^= zobPiece[Pc(side, P)][tsq]; p->bbTp[P] ^= SqBb(tsq); p->bbTp[ftp]^= SqBb(tsq); p->pcCount[side][ftp]++; p->pcCount[side][P]--; p->pieceMat[side] += Data.matValue[ftp]; p->phase += Data.phaseValue[ftp] - Data.phaseValue[P]; p->pstMg[side] += Data.pstMg[side][ftp][tsq] - Data.pstMg[side][P][tsq]; p->pstEg[side] += Data.pstEg[side][ftp][tsq] - Data.pstEg[side][P][tsq]; break; } p->side ^= 1; p->hashKey ^= SIDE_RANDOM; }