Beispiel #1
0
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))));
        }
    }
}
Beispiel #2
0
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];
}
Beispiel #3
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;
}
Beispiel #4
0
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
   }
}
Beispiel #5
0
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;
}