Beispiel #1
0
MoveStack* generate_non_capture_checks(const Position& pos, MoveStack* mlist) {

    assert(pos.is_ok());
    assert(!pos.is_check());

    Bitboard b, dc;
    Square from;
    Color us = pos.side_to_move();
    Square ksq = pos.king_square(opposite_color(us));

    assert(pos.piece_on(ksq) == piece_of_color_and_type(opposite_color(us), KING));

    // Discovered non-capture checks
    b = dc = pos.discovered_check_candidates(us);

    while (b)
    {
        from = pop_1st_bit(&b);
        switch (pos.type_of_piece_on(from))
        {
        case PAWN:   /* Will be generated togheter with pawns direct checks */
            break;
        case KNIGHT:
            mlist = generate_discovered_checks<KNIGHT>(pos, mlist, from);
            break;
        case BISHOP:
            mlist = generate_discovered_checks<BISHOP>(pos, mlist, from);
            break;
        case ROOK:
            mlist = generate_discovered_checks<ROOK>(pos, mlist, from);
            break;
        case KING:
            mlist = generate_discovered_checks<KING>(pos, mlist, from);
            break;
        default:
            assert(false);
            break;
        }
    }

    // Direct non-capture checks
    mlist = generate_direct_checks<PAWN>(pos, mlist, us, dc, ksq);
    mlist = generate_direct_checks<KNIGHT>(pos, mlist, us, dc, ksq);
    mlist = generate_direct_checks<BISHOP>(pos, mlist, us, dc, ksq);
    mlist = generate_direct_checks<ROOK>(pos, mlist, us, dc, ksq);
    return  generate_direct_checks<QUEEN>(pos, mlist, us, dc, ksq);
}
Beispiel #2
0
void solve_three_in_a_column(int board[MAX_SIZE][MAX_SIZE],
                             int size,
                             int col,
                             bool announce) {
	for (int col = 0; col < size; col++) {
		if (board[row][col] == board[row][col + 1] && board[row][col] != UNKNOWN) {
			board[row][col + 2] = opposite_color(board[row][col]);
			if (col > 0) {
				board[row][col - 1] = opposite_color(board[row][col]);
			}
		}
	}
	for (int col = 0; col < size; col++) {
		if (board[row][col] == board[row][col + 2] && board[row][col] != UNKNOWN) {
			board[row][col + 1] = opposite_color(board[row][col]);
		}
	}
}
Beispiel #3
0
int test_eval(const Position& pos) {
	Color us = pos.side_to_move();
	Color them = opposite_color(us);
	return 
			pos.piece_count(us, PAWN) 		* 100 +
			pos.piece_count(us, KNIGHT) 	* 150 +
			pos.piece_count(us, BISHOP) 	* 150 +
			pos.piece_count(us, ROOK) 		* 300 +
			pos.piece_count(us, QUEEN) 		* 600 -
			pos.piece_count(them, PAWN) 	* 100 -
			pos.piece_count(them, KNIGHT) 	* 150 -
			pos.piece_count(them, BISHOP) 	* 150 -
			pos.piece_count(them, ROOK) 	* 300 -
			pos.piece_count(them, QUEEN) 	* 600;
}
MoveStack* generate_captures(const Position& pos, MoveStack* mlist) {

  assert(pos.is_ok());
  assert(!pos.is_check());

  Color us = pos.side_to_move();
  Bitboard target = pos.pieces_of_color(opposite_color(us));

  mlist = generate_piece_moves<QUEEN>(pos, mlist, us, target);
  mlist = generate_piece_moves<ROOK>(pos, mlist, us, target);
  mlist = generate_piece_moves<BISHOP>(pos, mlist, us, target);
  mlist = generate_piece_moves<KNIGHT>(pos, mlist, us, target);
  mlist = generate_piece_moves<PAWN, CAPTURE>(pos, mlist, us, target);
  return  generate_piece_moves<KING>(pos, mlist, us, target);
}
Beispiel #5
0
ScaleFactor ScalingFunction<KPKP>::apply(const Position& pos) const {

  assert(pos.non_pawn_material(strongerSide) == VALUE_ZERO);
  assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
  assert(pos.piece_count(WHITE, PAWN) == 1);
  assert(pos.piece_count(BLACK, PAWN) == 1);

  Square wksq, bksq, wpsq;
  Color stm;

  if (strongerSide == WHITE)
  {
      wksq = pos.king_square(WHITE);
      bksq = pos.king_square(BLACK);
      wpsq = pos.piece_list(WHITE, PAWN, 0);
      stm = pos.side_to_move();
  }
  else
  {
      wksq = flip_square(pos.king_square(BLACK));
      bksq = flip_square(pos.king_square(WHITE));
      wpsq = flip_square(pos.piece_list(BLACK, PAWN, 0));
      stm = opposite_color(pos.side_to_move());
  }

  if (square_file(wpsq) >= FILE_E)
  {
      wksq = flop_square(wksq);
      bksq = flop_square(bksq);
      wpsq = flop_square(wpsq);
  }

  // If the pawn has advanced to the fifth rank or further, and is not a
  // rook pawn, it's too dangerous to assume that it's at least a draw.
  if (   square_rank(wpsq) >= RANK_5
      && square_file(wpsq) != FILE_A)
      return SCALE_FACTOR_NONE;

  // Probe the KPK bitbase with the weakest side's pawn removed. If it's a
  // draw, it's probably at least a draw even with the pawn.
  return probe_kpk(wksq, wpsq, bksq, stm) ? SCALE_FACTOR_NONE : SCALE_FACTOR_ZERO;
}
Beispiel #6
0
Value EvaluationFunction<KPK>::apply(const Position& pos) const {

  assert(pos.non_pawn_material(strongerSide) == VALUE_ZERO);
  assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
  assert(pos.piece_count(strongerSide, PAWN) == 1);
  assert(pos.piece_count(weakerSide, PAWN) == 0);

  Square wksq, bksq, wpsq;
  Color stm;

  if (strongerSide == WHITE)
  {
      wksq = pos.king_square(WHITE);
      bksq = pos.king_square(BLACK);
      wpsq = pos.piece_list(WHITE, PAWN, 0);
      stm = pos.side_to_move();
  }
  else
  {
      wksq = flip_square(pos.king_square(BLACK));
      bksq = flip_square(pos.king_square(WHITE));
      wpsq = flip_square(pos.piece_list(BLACK, PAWN, 0));
      stm = opposite_color(pos.side_to_move());
  }

  if (square_file(wpsq) >= FILE_E)
  {
      wksq = flop_square(wksq);
      bksq = flop_square(bksq);
      wpsq = flop_square(wpsq);
  }

  if (!probe_kpk(wksq, wpsq, bksq, stm))
      return VALUE_DRAW;

  Value result =  VALUE_KNOWN_WIN
                + PawnValueEndgame
                + Value(square_rank(wpsq));

  return strongerSide == pos.side_to_move() ? result : -result;
}
bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {

  assert(pos.is_ok());
  assert(move_is_ok(m));
  assert(pinned == pos.pinned_pieces(pos.side_to_move()));

  Color us = pos.side_to_move();
  Color them = opposite_color(us);
  Square from = move_from(m);
  Square to = move_to(m);
  Piece pc = pos.piece_on(from);

  // Use a slower but simpler function for uncommon cases
  if (move_is_ep(m) || move_is_castle(m))
      return move_is_legal(pos, m);

  // If the from square is not occupied by a piece belonging to the side to
  // move, the move is obviously not legal.
  if (color_of_piece(pc) != us)
      return false;

  // The destination square cannot be occupied by a friendly piece
  if (pos.color_of_piece_on(to) == us)
      return false;

  // Handle the special case of a pawn move
  if (type_of_piece(pc) == PAWN)
  {
      // Move direction must be compatible with pawn color
      int direction = to - from;
      if ((us == WHITE) != (direction > 0))
          return false;

      // A pawn move is a promotion iff the destination square is
      // on the 8/1th rank.
      if ((  (square_rank(to) == RANK_8 && us == WHITE)
           ||(square_rank(to) == RANK_1 && us != WHITE)) != bool(move_is_promotion(m)))
          return false;

      // Proceed according to the square delta between the origin and
      // destination squares.
      switch (direction)
      {
      case DELTA_NW:
      case DELTA_NE:
      case DELTA_SW:
      case DELTA_SE:
      // Capture. The destination square must be occupied by an enemy
      // piece (en passant captures was handled earlier).
          if (pos.color_of_piece_on(to) != them)
              return false;
          break;

      case DELTA_N:
      case DELTA_S:
      // Pawn push. The destination square must be empty.
          if (!pos.square_is_empty(to))
              return false;
          break;

      case DELTA_NN:
      // Double white pawn push. The destination square must be on the fourth
      // rank, and both the destination square and the square between the
      // source and destination squares must be empty.
      if (   square_rank(to) != RANK_4
          || !pos.square_is_empty(to)
          || !pos.square_is_empty(from + DELTA_N))
          return false;
          break;

      case DELTA_SS:
      // Double black pawn push. The destination square must be on the fifth
      // rank, and both the destination square and the square between the
      // source and destination squares must be empty.
          if (   square_rank(to) != RANK_5
              || !pos.square_is_empty(to)
              || !pos.square_is_empty(from + DELTA_S))
              return false;
          break;

      default:
          return false;
      }
      // The move is pseudo-legal, check if it is also legal
      return pos.is_check() ? pos.pl_move_is_evasion(m, pinned) : pos.pl_move_is_legal(m, pinned);
  }

  // Luckly we can handle all the other pieces in one go
  return    bit_is_set(pos.attacks_from(pc, from), to)
        && (pos.is_check() ? pos.pl_move_is_evasion(m, pinned) : pos.pl_move_is_legal(m, pinned))
        && !move_is_promotion(m);
}
MoveStack* generate_evasions(const Position& pos, MoveStack* mlist) {

  assert(pos.is_ok());
  assert(pos.is_check());

  Bitboard b, target;
  Square from, checksq;
  int checkersCnt = 0;
  Color us = pos.side_to_move();
  Square ksq = pos.king_square(us);
  Bitboard checkers = pos.checkers();
  Bitboard sliderAttacks = EmptyBoardBB;

  assert(pos.piece_on(ksq) == piece_of_color_and_type(us, KING));
  assert(checkers);

  // Find squares attacked by slider checkers, we will remove
  // them from the king evasions set so to early skip known
  // illegal moves and avoid an useless legality check later.
  b = checkers;
  do
  {
      checkersCnt++;
      checksq = pop_1st_bit(&b);

      assert(pos.color_of_piece_on(checksq) == opposite_color(us));

      switch (pos.type_of_piece_on(checksq))
      {
      case BISHOP: sliderAttacks |= BishopPseudoAttacks[checksq]; break;
      case ROOK:   sliderAttacks |= RookPseudoAttacks[checksq];   break;
      case QUEEN:
          // In case of a queen remove also squares attacked in the other direction to
          // avoid possible illegal moves when queen and king are on adjacent squares.
          if (direction_is_straight(checksq, ksq))
              sliderAttacks |= RookPseudoAttacks[checksq] | pos.attacks_from<BISHOP>(checksq);
          else
              sliderAttacks |= BishopPseudoAttacks[checksq] | pos.attacks_from<ROOK>(checksq);
      default:
          break;
      }
  } while (b);

  // Generate evasions for king, capture and non capture moves
  b = pos.attacks_from<KING>(ksq) & ~pos.pieces_of_color(us) & ~sliderAttacks;
  from = ksq;
  SERIALIZE_MOVES(b);

  // Generate evasions for other pieces only if not double check
  if (checkersCnt > 1)
      return mlist;

  // Find squares where a blocking evasion or a capture of the
  // checker piece is possible.
  target = squares_between(checksq, ksq) | checkers;

  mlist = generate_piece_moves<PAWN, EVASION>(pos, mlist, us, target);
  mlist = generate_piece_moves<KNIGHT>(pos, mlist, us, target);
  mlist = generate_piece_moves<BISHOP>(pos, mlist, us, target);
  mlist = generate_piece_moves<ROOK>(pos, mlist, us, target);
  return  generate_piece_moves<QUEEN>(pos, mlist, us, target);
}
MaterialInfo *MaterialInfoTable::get_material_info(const Position &pos) {
  Key key = pos.get_material_key();
  int index = key & (size - 1);
  MaterialInfo *mi = entries + index;

  // If mi->key matches the position's material hash key, it means that we 
  // have analysed this material configuration before, and we can simply
  // return the information we found the last time instead of recomputing it:
  if(mi->key == key)
    return mi;

  // Clear the MaterialInfo object, and set its key:
  mi->clear();
  mi->key = key;

  // A special case before looking for a specialized evaluation function:
  // KNN vs K is a draw:
  if(key == KNNKMaterialKey || key == KKNNMaterialKey) {
    mi->factor[WHITE] = mi->factor[BLACK] = 0;
    return mi;
  }

  // Let's look if we have a specialized evaluation function for this
  // particular material configuration:
  if(key == KPKMaterialKey) {
    mi->evaluationFunction = &EvaluateKPK;
    return mi;
  }
  else if(key == KKPMaterialKey) {
    mi->evaluationFunction = &EvaluateKKP;
    return mi;
  }
  else if(key == KBNKMaterialKey) {
    mi->evaluationFunction = &EvaluateKBNK;
    return mi;
  }
  else if(key == KKBNMaterialKey) {
    mi->evaluationFunction = &EvaluateKKBN;
    return mi;
  }
  else if(key == KRKPMaterialKey) {
    mi->evaluationFunction = &EvaluateKRKP;
    return mi;
  }
  else if(key == KPKRMaterialKey) {
    mi->evaluationFunction = &EvaluateKPKR;
    return mi;
  }
  else if(key == KRKBMaterialKey) {
    mi->evaluationFunction = &EvaluateKRKB;
    return mi;
  }
  else if(key == KBKRMaterialKey) {
    mi->evaluationFunction = &EvaluateKBKR;
    return mi;
  }
  else if(key == KRKNMaterialKey) {
    mi->evaluationFunction = &EvaluateKRKN;
    return mi;
  }
  else if(key == KNKRMaterialKey) {
    mi->evaluationFunction = &EvaluateKNKR;
    return mi;
  }
  else if(key == KQKRMaterialKey) {
    mi->evaluationFunction = &EvaluateKQKR;
    return mi;
  }
  else if(key == KRKQMaterialKey) {
    mi->evaluationFunction = &EvaluateKRKQ;
    return mi;
  }
  else if(key == KBBKNMaterialKey) {
    mi->evaluationFunction = &EvaluateKBBKN;
    return mi;
  }
  else if(key == KNKBBMaterialKey) {
    mi->evaluationFunction = &EvaluateKNKBB;
    return mi;
  }
  else if(pos.non_pawn_material(BLACK) == Value(0) &&
          pos.pawn_count(BLACK) == 0 &&
          pos.non_pawn_material(WHITE) >= RookValueEndgame) {
    mi->evaluationFunction = &EvaluateKXK;
    return mi;
  }
  else if(pos.non_pawn_material(WHITE) == Value(0) &&
          pos.pawn_count(WHITE) == 0 &&
          pos.non_pawn_material(BLACK) >= RookValueEndgame) {
    mi->evaluationFunction = &EvaluateKKX;
    return mi;
  }
  else if(pos.pawns() == EmptyBoardBB && pos.rooks() == EmptyBoardBB
          && pos.queens() == EmptyBoardBB) {
    // Minor piece endgame with at least one minor piece per side,
    // and no pawns.
    assert(pos.knights(WHITE) | pos.bishops(WHITE));
    assert(pos.knights(BLACK) | pos.bishops(BLACK));

    if(pos.bishop_count(WHITE) + pos.knight_count(WHITE) <= 2
       && pos.bishop_count(BLACK) + pos.knight_count(BLACK) <= 2) {
      mi->evaluationFunction = &EvaluateKmmKm;
      return mi;
    }
  }    

  // OK, we didn't find any special evaluation function for the current
  // material configuration.  Is there a suitable scaling function?
  //
  // The code below is rather messy, and it could easily get worse later,
  // if we decide to add more special cases.  We face problems when there
  // are several conflicting applicable scaling functions and we need to
  // decide which one to use.

  if(key == KRPKRMaterialKey) {
    mi->scalingFunction[WHITE] = &ScaleKRPKR;
    return mi;
  }
  if(key == KRKRPMaterialKey) {
    mi->scalingFunction[BLACK] = &ScaleKRKRP;
    return mi;
  }
  if(key == KRPPKRPMaterialKey) {
    mi->scalingFunction[WHITE] = &ScaleKRPPKRP;
    return mi;
  }
  else if(key == KRPKRPPMaterialKey) {
    mi->scalingFunction[BLACK] = &ScaleKRPKRPP;
    return mi;
  }
  if(key == KBPKBMaterialKey) {
    mi->scalingFunction[WHITE] = &ScaleKBPKB;
    return mi;
  }
  if(key == KBKBPMaterialKey) {
    mi->scalingFunction[BLACK] = &ScaleKBKBP;
    return mi;
  }
  if(key == KBPKNMaterialKey) {
    mi->scalingFunction[WHITE] = &ScaleKBPKN;
    return mi;
  }
  if(key == KNKBPMaterialKey) {
    mi->scalingFunction[BLACK] = &ScaleKNKBP;
    return mi;
  }
  if(key == KNPKMaterialKey) {
    mi->scalingFunction[WHITE] = &ScaleKNPK;
    return mi;
  }
  if(key == KKNPMaterialKey) {
    mi->scalingFunction[BLACK] = &ScaleKKNP;
    return mi;
  }

  if(pos.non_pawn_material(WHITE) == BishopValueMidgame &&
     pos.bishop_count(WHITE) == 1 && pos.pawn_count(WHITE) >= 1)
    mi->scalingFunction[WHITE] = &ScaleKBPK;
  if(pos.non_pawn_material(BLACK) == BishopValueMidgame &&
     pos.bishop_count(BLACK) == 1 && pos.pawn_count(BLACK) >= 1)
    mi->scalingFunction[BLACK] = &ScaleKKBP;

  if(pos.pawn_count(WHITE) == 0 &&
     pos.non_pawn_material(WHITE) == QueenValueMidgame &&
     pos.queen_count(WHITE) == 1 &&
     pos.rook_count(BLACK) == 1 && pos.pawn_count(BLACK) >= 1)
    mi->scalingFunction[WHITE] = &ScaleKQKRP;
  else if(pos.pawn_count(BLACK) == 0 &&
          pos.non_pawn_material(BLACK) == QueenValueMidgame &&
          pos.queen_count(BLACK) == 1 &&
          pos.rook_count(WHITE) == 1 && pos.pawn_count(WHITE) >= 1)
    mi->scalingFunction[BLACK] = &ScaleKRPKQ;

  if(pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) == Value(0)) {
    if(pos.pawn_count(BLACK) == 0) {
      assert(pos.pawn_count(WHITE) >= 2);
      mi->scalingFunction[WHITE] = &ScaleKPsK;
    }
    else if(pos.pawn_count(WHITE) == 0) {
      assert(pos.pawn_count(BLACK) >= 2);
      mi->scalingFunction[BLACK] = &ScaleKKPs;
    }
    else if(pos.pawn_count(WHITE) == 1 && pos.pawn_count(BLACK) == 1) {
      mi->scalingFunction[WHITE] = &ScaleKPKPw;
      mi->scalingFunction[BLACK] = &ScaleKPKPb;
    }
  }

  // Compute the space weight
  if(pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) >=
     2*QueenValueMidgame + 4*RookValueMidgame + 2*KnightValueMidgame) {
    int minorPieceCount =
      pos.knight_count(WHITE) + pos.knight_count(BLACK)
      + pos.bishop_count(WHITE) + pos.bishop_count(BLACK);
    mi->spaceWeight = minorPieceCount * minorPieceCount;
  }

  // Evaluate the material balance.
  
  Color c;
  int sign;
  Value egValue = Value(0), mgValue = Value(0);
  
  for(c = WHITE, sign = 1; c <= BLACK; c++, sign = -sign) {

    // No pawns makes it difficult to win, even with a material advantage:
    if(pos.pawn_count(c) == 0 &&
       pos.non_pawn_material(c) - pos.non_pawn_material(opposite_color(c))
       <= BishopValueMidgame) {
      if(pos.non_pawn_material(c) == pos.non_pawn_material(opposite_color(c)))
        mi->factor[c] = 0;
      else if(pos.non_pawn_material(c) < RookValueMidgame)
        mi->factor[c] = 0;
      else {
        switch(pos.bishop_count(c)) {
        case 2:
          mi->factor[c] = 32; break;
        case 1:
          mi->factor[c] = 12; break;
        case 0:
          mi->factor[c] = 6; break;
        }
      }
    }
    
    // Bishop pair:
    if(pos.bishop_count(c) >= 2) {
      mgValue += sign * BishopPairMidgameBonus;
      egValue += sign * BishopPairEndgameBonus;
    }

    // Knights are stronger when there are many pawns on the board.  The 
    // formula is taken from Larry Kaufman's paper "The Evaluation of Material
    // Imbalances in Chess": 
    // http://mywebpages.comcast.net/danheisman/Articles/evaluation_of_material_imbalance.htm
    mgValue += sign * Value(pos.knight_count(c)*(pos.pawn_count(c)-5)*16);
    egValue += sign * Value(pos.knight_count(c)*(pos.pawn_count(c)-5)*16);

    // Redundancy of major pieces, again based on Kaufman's paper:
    if(pos.rook_count(c) >= 1) {
      Value v = Value((pos.rook_count(c) - 1) * 32 + pos.queen_count(c) * 16);
      mgValue -= sign * v;
      egValue -= sign * v;
    }
      
  }

  mi->mgValue = int16_t(mgValue);
  mi->egValue = int16_t(egValue);

  return mi;
}
Beispiel #10
0
QString rubiks_or_not(QStringList list, int *error)
{
    QStringList yellow_wall, opposite_wall, mid_line;
    yellow_wall = list.filter("yellow");

    QString opposite = opposite_color(yellow_wall, error);
    opposite_wall = list.filter(opposite);

    foreach (const QString &str, list)
    {
        if (!str.contains("yellow") && !str.contains(opposite))
        {
            mid_line += str;
        }
    }

    yellow_wall = order(yellow_wall, "yellow");
    opposite_wall = order(opposite_wall, opposite);

    if(*error != 0)
    {
        return "error";
    }

    if(yellow_wall.count() != 8 || yellow_wall.count() != opposite_wall.count() || mid_line.count() != 4)
    {
        //Incorrect combination of colors
        *error = 12;
        return "error";
    }
    else
    {
        QString color_check_1, color_check_2;
        int count_check_1 = 0, count_check_2 = 0;
        for(int i = 0; i < mid_line.count(); i++)
        {
            for(int j = 0; j < yellow_wall.count(); j++)
            {
                color_check_1 = mid_line.at(i);
                color_check_2 = color_check_1.section('\n', 1, 1)+'\n'+color_check_1.section('\n', 0, 0);
                if(yellow_wall.at(j).contains(color_check_1))
                {
                    color_check_1 = "used";
                    count_check_1++;
                }
                else if(yellow_wall.at(j).contains(color_check_2))
                {
                    color_check_2 = "used";
                    count_check_1++;
                }

                if(opposite_wall.at(j).contains(color_check_1) && color_check_1 != "used")
                {
                    count_check_1++;
                }
                else if(opposite_wall.at(j).contains(color_check_2) && color_check_2 != "used")
                {
                    count_check_2++;
                }
            }
            if(count_check_2 != count_check_1)
            {
                //Incorrect combination of colors for cubes containing three colors
                *error = 13;
                return "error";
            }
            else
            {
                count_check_1 = 0;
                count_check_2 = 0;
            }
        }

    }

    return opposite;
}