static void UCIMoveImage(const Move &move, ostream &image) { if (IsNull(move)) { image << "NULL"; } else { image << FileImage(StartSquare(move)); image << RankImage(StartSquare(move)); image << FileImage(DestSquare(move)); image << RankImage(DestSquare(move)); if (TypeOfMove(move) == Promotion) { ASSERT(PromoteTo(move)<16); image << (char)tolower(PieceImage(TypeOfPiece(PromoteTo(move)))); } } }
int see( const Board &board, Move move ) { ASSERT(!IsNull(move)); #ifdef ATTACK_TRACE cout << "see "; MoveImage(move,cout); cout << endl; #endif ColorType my_side = PieceColor(board[StartSquare(move)]); ColorType side = my_side; ColorType oside = OppositeColor(side); Square square = DestSquare(move); Square attack_square = StartSquare(move); Piece attacker = board[attack_square]; Piece on_square = (TypeOfMove(move) == EnPassant) ? MakePiece(Pawn,oside) : board[square]; Bitboard opp_attacks(board.calcAttacks(square,oside)); if (opp_attacks.isClear()) { // piece is undefended #ifdef ATTACK_TRACE cout << "undefended, returning " << Gain(move) << endl; #endif return Gain(move); } int score_list[20]; int swap_score = 0; int gain; Bitboard attacks[2]; Square last_attack_sq[2] = {InvalidSquare, InvalidSquare}; attacks[side] = board.calcAttacks(square,side); attacks[oside] = opp_attacks; int count = 0; for (;;) { last_attack_sq[side] = attack_square; attacker = board[attack_square]; #ifdef ATTACK_TRACE cout << " " << PieceImage(TypeOfPiece(attacker)) << " on " << FileImage(attack_square) << RankImage(attack_square) << " takes " << PieceImage(TypeOfPiece(on_square)) << endl; #endif gain = PieceValue(on_square); if (TypeOfPiece(attacker) == Pawn && Rank(square,side) == 8) { if (count == 0) { // initial capture is a promotion (could be under-promotion) gain += (PieceValues[PromoteTo(move)] - PAWN_VALUE); on_square = MakePiece(PromoteTo(move),side); } else { // assume Queen promotion gain += QUEEN_VALUE-PAWN_VALUE; on_square = MakePiece(Queen,side); } } else { on_square = attacker; } if (side == my_side) swap_score += gain; else swap_score -= gain; ASSERT(count < 20); score_list[count++] = swap_score; // remove piece we used from attacks attacks[side].clear(attack_square); // switch sides side = OppositeColor(side); const Square atk = last_attack_sq[side]; if (atk != InvalidSquare && TypeOfPiece(board[atk]) != Knight) { // add in x-ray attacks if any Square xray = board.getDirectionalAttack(atk, -Attacks::directions[atk][square], side); if (xray != InvalidSquare) { attacks[side].set(xray); } } if (attacks[side]) { // get next opponent attacker attack_square = minAttacker(board,attacks[side],side); } else { // no more attackers (including x-rays) break; } } ASSERT(count >= 1); // minimax over the score list for (int i = count-1; i > 0; --i) { if (i % 2 == 0) { score_list[i-1] = max(score_list[i],score_list[i-1]); } else { score_list[i-1] = min(score_list[i],score_list[i-1]); } } #ifdef ATTACK_TRACE cout << "returning " << score_list[0] << endl; #endif return score_list[0]; }
int seeSign( const Board &board, Move move, int threshold ) { ASSERT(!IsNull(move)); #ifdef ATTACK_TRACE cout << "see "; MoveImage(move,cout); cout << endl; #endif ColorType my_side = PieceColor(board[StartSquare(move)]); ColorType side = my_side; ColorType oside = OppositeColor(side); Square square = DestSquare(move); Square attack_square = StartSquare(move); Piece attacker = board[attack_square]; Piece on_square = (TypeOfMove(move) == EnPassant) ? MakePiece(Pawn,oside) : board[square]; Bitboard opp_attacks(board.calcAttacks(square,oside)); if (opp_attacks.isClear()) { // piece is undefended #ifdef ATTACK_TRACE cout << "undefended, returning " << (Gain(move) >= threshold) << endl; #endif return Gain(move) >= threshold; } int score_list[20]; int swap_score = 0; int gain; Bitboard attacks[2]; Square last_attack_sq[2] = {InvalidSquare, InvalidSquare}; attacks[side] = board.calcAttacks(square,side); attacks[oside] = opp_attacks; int count = 0; for (;;) { last_attack_sq[side] = attack_square; attacker = board[attack_square]; #ifdef ATTACK_TRACE cout << " " << PieceImage(TypeOfPiece(attacker)) << " on " << FileImage(attack_square) << RankImage(attack_square) << " takes " << PieceImage(TypeOfPiece(on_square)) << endl; #endif gain = PieceValue(on_square); if (TypeOfPiece(attacker) == Pawn && Rank(square,side) == 8) { if (count == 0) { // initial capture is a promotion (could be under-promotion) gain += (PieceValues[PromoteTo(move)] - PAWN_VALUE); on_square = MakePiece(PromoteTo(move),side); } else { // assume Queen promotion gain += QUEEN_VALUE-PAWN_VALUE; on_square = MakePiece(Queen,side); } } else { on_square = attacker; } if (side == my_side) swap_score += gain; else swap_score -= gain; ASSERT(count < 20); score_list[count++] = swap_score; // remove piece we used from attacks attacks[side].clear(attack_square); // switch sides side = OppositeColor(side); if (count % 2 == 0) { // If it is our turn to move and we are above the threshold // then we can exit - if we capture it only improves the score. if (swap_score >= threshold) { ASSERT(see(board,move) >= threshold); return 1; } // Futility: If capturing the opponent piece for free does // not bring us up to the threshold, exit. (Do not cut off // if we have a potential promotion). if ((Rank(square,side) != 8 || !(attacks[side] & board.pawn_bits[side])) && swap_score + PieceValue(on_square) < threshold) { ASSERT(see(board,move) < threshold); return 0; } } else { // See if opponent already has captured enough that SEE is // below threshold if (swap_score < threshold) { ASSERT(see(board,move) < threshold); return 0; } // Futility: opponent capture cannot get us below threshold if ((Rank(square,side) != 8 || !(attacks[side] & board.pawn_bits[side])) && swap_score - PieceValue(on_square) >= threshold) { ASSERT(see(board,move) >= threshold); return 1; } } const Square atk = last_attack_sq[side]; if (atk != InvalidSquare && TypeOfPiece(board[atk]) != Knight) { // add in x-ray attacks if any Square xray = board.getDirectionalAttack(atk, -Attacks::directions[atk][square], side); if (xray != InvalidSquare) { attacks[side].set(xray); } } if (attacks[side]) { // get next opponent attacker attack_square = minAttacker(board,attacks[side],side); } else { // no more attackers (including x-rays) break; } } ASSERT(count >= 1); // minimax over the score list for (int i = count-1; i > 0; --i) { if (i % 2 == 0) { score_list[i-1] = max(score_list[i],score_list[i-1]); } else { score_list[i-1] = min(score_list[i],score_list[i-1]); } } #ifdef ATTACK_TRACE cout << "returning " << (score_list[0]>=threshold) << endl; #endif ASSERT((score_list[0] >= threshold) == (see(board,move) >= threshold)); return score_list[0] >= threshold; }
void Notation::image(const Board & b, const Move & m, OutputFormat format, ostream &image) { if (format == UCI) { return UCIMoveImage(m,image); } else if (format == WB_OUT) { if (TypeOfMove(m) == KCastle) { image << "O-O"; } else if (TypeOfMove(m) == QCastle) { image << "O-O-O"; } else { image << FileImage(StartSquare(m)); image << RankImage(StartSquare(m)); image << FileImage(DestSquare(m)); image << RankImage(DestSquare(m)); if (TypeOfMove(m) == Promotion) { // N.b. ICS requires lower case. image << (char)tolower((int)PieceImage(PromoteTo(m))); } } return; } // format is SAN if (IsNull(m)) { image << "(null)"; return; } PieceType p = PieceMoved(m); ASSERT(p != Empty); if (TypeOfMove(m) == KCastle) { image << "O-O"; } else if (TypeOfMove(m) == QCastle) { image << "O-O-O"; } else { if (p == Pawn) { if (Capture(m) == Empty) { image << FileImage(DestSquare(m)); image << RankImage(DestSquare(m)); } else { image << FileImage(StartSquare(m)); image << 'x'; image << FileImage(DestSquare(m)); image << RankImage(DestSquare(m)); } if (TypeOfMove(m) == Promotion) { image << '='; image << PieceImage(PromoteTo(m)); } } else { image << PieceImage(p); Bitboard attacks = b.calcAttacks(DestSquare(m), b.sideToMove()); unsigned n = attacks.bitCount(); int dups = 0; int filedups = 0; int rankdups = 0; int files[9]; int ranks[9]; if (n > 1) { Square sq; while (attacks.iterate(sq)) { if (TypeOfPiece(b[sq]) == p) { files[dups] = File(sq); if (files[dups] == File(StartSquare(m))) filedups++; ranks[dups] = Rank(sq,White); if (ranks[dups] == Rank(StartSquare(m),White)) rankdups++; ++dups; } } } if (dups > 1) { // need to disambiguate move. if (filedups == 1) { image << FileImage(StartSquare(m)); } else if (rankdups == 1) { image << RankImage(StartSquare(m)); } else { // need both rank and file to disambiguate image << FileImage(StartSquare(m)); image << RankImage(StartSquare(m)); } } if (Capture(m) != Empty) { image << 'x'; } image << FileImage(DestSquare(m)); image << RankImage(DestSquare(m)); } } Board board_copy(b); board_copy.doMove(m); if (board_copy.checkStatus() == InCheck) { Move moves[Constants::MaxMoves]; MoveGenerator mg(board_copy); if (mg.generateEvasions(moves)) image << '+'; else image << '#'; // mate } }
int do_eco(const string &eco_line) { ColorType side = White; Board board; int movecount = 0; stringstream s(eco_line); const string &str = s.str(); string::const_iterator it = str.begin(); // Follow the opening line string token; string code; string name; int first_token = 1; while (it != str.end()) { // skip spaces while (isspace(*it) && it != str.end()) it++; if (it == str.end()) break; // extract text string text; int first = 1; int quoted = 0; while (it != str.end() && (quoted ? (*it != '"') : !isspace(*it))) { if (first && *it == '"') { quoted++; it++; first = 0; continue; } text += *it++; } if (first_token) { code = text; first_token = 0; continue; } else if (quoted) { name = text; break; } else if (text.length() == 0) { break; } // skip numbers if (isdigit(text[0])) continue; if (!isalpha(text[0])) return -1; // parse the move Move m = Notation::value(board,side,Notation::SAN_IN,text); if (IsNull(m) || !legalMove(board,StartSquare(m),DestSquare(m))) { cerr << "Illegal or invalid move: " << text << endl; return -1; } else { ++movecount; board.doMove(m); } side = OppositeColor(side); } if (code.length()) { cout << '{' << '"' << code << '"' << ", "; write_64(board.hashCode(),cout); cout << " ,"; if (name.length()) cout << '"' << name << '"'; else cout << '"' << '"'; cout << "},"; cout << endl; } return 0; }