int main(){ clock_t start,end; double timer; start=clock(); file=fopen("soma_cube_answers.txt","w"); Cube space; int x,y,z; for(x=0;x<=4;x++){for(y=0;y<=4;y++){for(z=0;z<=4;z++){ if(x==0||x==4||y==0||y==4||z==0||z==4){space.form[x][y][z]=9;} //outer wall else{space.form[x][y][z]=0;} }}} Piece p[8]={}; int i; for(i=1;i<=PIECENUM;i++){ p[i]=MakePiece(i); } Construct(space,p,1); WriteAns(ans,ansnum); fclose(file); end=clock(); timer=difftime(end,start)/(double)CLOCKS_PER_SEC; printf("search time: %.3f\n",timer); printf("open \"soma_cube_answers.txt\"\nto view %d answers\n",ansnum); return 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]; }
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; }