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); }
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]); } } }
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); }
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; }
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; }
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; }