void doBattle(batstat *batstats, bprotocol *aProtocol, int phase) { int attackingShip; int targetShip; group *attackingGroup; group *targetGroup; batstat *attackingSide; batstat *targetSide; int gun; pdebug(DFULL, "doBattle\n"); resetSides(batstats); while (!isDraw(batstats) && !isWon(batstats)) { while (attackersLeft(batstats)) { attackingGroup = selectAttackingGroup(batstats, &attackingSide, &attackingShip); assert(attackingGroup); attackingGroup->flags |= phase; for (gun = 0; gun < attackingGroup->type->attacks; gun++) { targetGroup = selectTargetGroup(attackingSide, &targetSide, &targetShip); if (targetGroup) { targetGroup->flags |= phase; attack(aProtocol, attackingSide, attackingGroup, attackingShip, targetSide, targetGroup, targetShip); } } } resetSides(batstats); } }
int Evaluation::evaluate(ChessBoard& cb, int alpha, int beta) { int score,i; evalFunction efunc; if (cb.move50draw > 98) return drawscore[cb.toMove]; scanBoard(cb); if (gamestage < 3000) isEndgame = true; else isEndgame = false; evalPawnstructure(cb); if (isEndgame) { if (isDraw(cb)) return drawscore[cb.toMove]; evalStaticEndgame(cb); // try a alphabeta cut score = (cb.toMove == WHITE) ? (position[WHITE] - position[BLACK]) : (position[BLACK] - position[WHITE]); if ((score < (alpha - 300)) || (score > (beta + 300))) return score; i = 0; while (efunc = fEndGame[i++]) (this->*efunc)(cb); score = (cb.toMove == WHITE) ? (position[WHITE] - position[BLACK]) : (position[BLACK] - position[WHITE]); // Correct the score if there isn't any winchances to force 3 fold rep. if (cantWin(cb)) score = drawscore[cb.toMove] - 1; else if (cantLose(cb)) score = drawscore[cb.toMove] + 1; } else { evalStatic(cb); // try a alphabeta cut score = (cb.toMove == WHITE) ? (position[WHITE] - position[BLACK]) : (position[BLACK] - position[WHITE]); if ((score < (alpha - 300)) || (score >(beta + 300))) return score; i = 0; while (efunc = fMiddleGame[i++]) (this->*efunc)(cb); score = (cb.toMove == WHITE) ? (position[WHITE] - position[BLACK]) : (position[BLACK] - position[WHITE]); } return score; }
int heuristicForState(GameState* gs, int player, int other) { if (isDraw(gs)) return 0; int term_stat = getWinner(gs); if (term_stat == player) return 1000; if (term_stat) return -1000; return getHeuristic(gs, player, other); }
void checkWin(GameState* gs) { int win = getWinner(gs); if (win) { printf("Game over! %d wins!\n", win); printGameState(gs); exit(0); } if (isDraw(gs)) { printf("Game over! Draw!\n"); printGameState(gs); exit(0); } }
/*! Slot to check if the current game is over, returns boolean value. */ bool TicTacEngine::isGameOver() { bool gameOver(false); int theWinner = winner(); if (theWinner != GameModel::None) { qDebug() << "TicTacEngine::isGameOver(): Yes!"; gameOver = true; setStatus(GameOver); } else if (isDraw()) { gameOver = true; setStatus(GameOver); } return gameOver; }
int findDrawLocation(){ int cycle =currentState.round - twoOfPowerState.round; State state1; State state2; copyState(&state1, &initState); copyState(&state2, &initState); int cycleCount = cycle; while(cycleCount-- /** debugging , cycle--**/ ){ dispatchOneCard( &state2); darwCardsFromPack( &state2); state2.round++; getWhichTurn( &state2); } int i=15; /** int i=14; debugging, because round is start by 1**/ for ( ;i<=currentState.round;i++ ){ dispatchOneCard( &state1); darwCardsFromPack( &state1); dispatchOneCard( &state2); darwCardsFromPack( &state2); if (isDraw(&state1 , &state2) ==1 ){ return state1.round + cycle; /**debugging return state1.round; **/ } state1.round++; state2.round++; getWhichTurn( &state1); getWhichTurn( &state2); } return -1; }
int main(){ #if !defined(ONLINE_JUDGE) freopen("246.in","r",stdin); ///freopen("error_input.txt","r",stdin); freopen("output.txt","w",stdout); #endif currentState = getNewState(); initState = getNewState(); twoOfPowerState = getNewState(); int i=0; int topCard=0; while ( scanf("%d",&topCard) != EOF && topCard ){ clearState(¤tState); clearState(&initState); clearState(&twoOfPowerState); currentState.handCard[51] = topCard; for(i=0;i<51;i++){ scanf("%d",¤tState.handCard[50-i]); } currentState.handCardLength =52; currentState.round = 1; /** debugging for round start with 1 **/ for (i=1;i<=14;i++){ /** turn = getWhichTurn( ¤tState); debug for all cardsLength is zero **/ int handCard = currentState.handCard[ (currentState.handCardLength -1) ]; int cardLength = currentState.cardsLength[currentState.whichTurn]; currentState.cards[currentState.whichTurn][ cardLength] =handCard; currentState.handCardLength--; currentState.cardsLength[currentState.whichTurn]++; if ( is2OfPower(i) >0 ){ copyState( &twoOfPowerState , ¤tState); } outputForDebug(¤tState); /** debugging , put on the last part after dispatching card.**/ currentState.whichTurn= (currentState.whichTurn +1 ) % 7; currentState.round ++; /** debugging put it than copyState **/ } copyState(&initState, ¤tState); /** use initSate when try to find loop's location. **/ while (1){ /** for debugging if ( currentState.round == 82 ){ int bbb=1; } **/ dispatchOneCard( ¤tState); darwCardsFromPack( ¤tState); if ( currentState.handCardLength == 52){ printf("Win : %d\n", currentState.round); break; }else if ( currentState.handCardLength ==0 ){ printf("Loss: %d\n", currentState.round); break; }else if (isDraw(¤tState, &twoOfPowerState)>0 ){ int roundLocation = findDrawLocation(); printf("Draw: %d\n", roundLocation); break; } /** debugging, should be put behind isDraw()!! before copying currentState to towOfPowerState, it should be done the isDraw action. **/ if ( is2OfPower(currentState.round ) >0 ){ /**debugging is2OfPower(i) **/ copyState( &twoOfPowerState , ¤tState); } currentState.round++; getWhichTurn( ¤tState ); } } return 0; }
int isGameDraw() { return isDraw(globalState); }
int getWeight(GameTreeNode* node, int movesLeft) { int toR, move, best_weight; if (getWinner(node->gs) || isDraw(node->gs) || movesLeft == 0) return heuristicForState(node->gs, node->player, node->other_player); GameState** possibleMoves = (GameState**) malloc(sizeof(GameState*) * node->gs->width); int validMoves = 0; for (int possibleMove = 0; possibleMove < node->gs->width; possibleMove++) { if (!canMove(node->gs, possibleMove)) { continue; } possibleMoves[validMoves] = stateForMove(node->gs, possibleMove, (node->turn ? node->player : node->other_player)); validMoves++; } // order possibleMoves by the heuristic g_node = node; if (node->turn) { // qsort_r is apparently non-standard, and won't work with emscripten. So we'll need to use a global. qsort(possibleMoves, validMoves, sizeof(GameState*), ascComp); } else { qsort(possibleMoves, validMoves, sizeof(GameState*), desComp); } best_weight = (node->turn ? INT_MIN : INT_MAX); for (move = 0; move < validMoves; move++) { // see if the game state is already in the hash table GameState* inTable = lookupInTable(node->ht, possibleMoves[move]); int child_weight; int child_last_move; if (inTable != NULL) { child_weight = inTable->weight; child_last_move = possibleMoves[move]->last_move; } else { GameTreeNode* child = newGameTreeNode(possibleMoves[move], node->player, node->other_player, !(node->turn), node->alpha, node->beta, node->ht); child_weight = getWeight(child, movesLeft - 1); child_last_move = child->gs->last_move; free(child); } possibleMoves[move]->weight = child_weight; addToTable(node->ht, possibleMoves[move]); if (movesLeft == LOOK_AHEAD) printf("Move %d has weight %d\n", child_last_move, child_weight); // alpha-beta pruning if (!node->turn) { // min node if (child_weight <= node->alpha) { // MAX ensures we will never go here toR = child_weight; goto done; } node->beta = (node->beta < child_weight ? node->beta : child_weight); } else { // max node if (child_weight >= node->beta) { // MIN ensures we will never go here toR = child_weight; goto done; } node->alpha = (node->alpha > child_weight ? node->alpha : child_weight); } if (!(node->turn)) { // min node if (best_weight > child_weight) { best_weight = child_weight; node->best_move = child_last_move; } } else { // max node if (best_weight < child_weight) { best_weight = child_weight; node->best_move = child_last_move; } } } toR = best_weight; done: for (int i = 0; i < validMoves; i++) { freeGameState(possibleMoves[i]); } free(possibleMoves); return toR; }
int Engine::QuiescenceSearch(int alpha,int beta) { //quisctime.Start(); if (isDraw()) return 0; nodes++; if(nodes%CheckupNodeCount == 0) { checkup(); //nodes = 0; } /*if(pos.getGameStatus()!=STATUS_NOTOVER) { int val = LeafEval(alpha,beta); if(val >= beta) return beta; else if(val < alpha) return alpha; return val; }*/ int stand_pat = 0; //ProbeStruct probe = Table.Probe(pos.TTKey, -1, alpha, beta); //if (probe.found && probe.entry->bound == TT_EXACT) //{ // return probe.score; // stand_pat = probe.score; //use TT probe as leafeval //} //else //{ stand_pat = LeafEval<false>(); //} if(stand_pat >= beta) //standpat { return stand_pat; } if(stand_pat <= alpha-PieceMaterial[PIECE_QUEEN]) //big delta pruning { return stand_pat; } if(alpha < stand_pat) { alpha = stand_pat; } Move m; int score = 0; vector<Move> vec; //generate moves vec.reserve(128); //movegentime.Start(); pos.generateCaptures(vec); //pos.generatePawnPushes(vec); //movegentime.Stop(); //vector<int> scores; //generate move scores //scores.reserve(128); //generateCaptureScores(vec, scores); int material = getBoardMaterial<COLOR_WHITE>()+getBoardMaterial<COLOR_BLACK>(); Move bestmove = CONS_NULLMOVE; int bound = TT_ALPHA; for(int i = 0;i<vec.size();i++) { //m = getHighestScoringMove(vec,i); m = vec[i]; int special = m.getSpecial(); int captured = m.getCapturedPiece(); if ((stand_pat + PieceMaterial[getSquare2Piece(captured)] + 200 < alpha) //delta pruning && (special != PIECE_QUEEN && special != PIECE_KNIGHT && special != PIECE_ROOK && special != PIECE_BISHOP) //not a promotion //&& (material > EndgameMaterial) ) { continue; } if (StaticExchangeEvaluation(m.getTo(), m.getFrom(), m.getMovingPiece(), captured) < 0) continue; //break; //since moves are sorted by SEE, we know remaining moves will also have SEE<0 //if (getSquare2Piece(m.getCapturedPiece()) == PIECE_KING) //captured opponent king // return CONS_INF; if(!pos.makeMove(m)) { continue; } //pos.forceMove(m); ply++; if (ply > SelectiveDepth) { SelectiveDepth = ply; } score = -QuiescenceSearch(-beta,-alpha); pos.unmakeMove(m); ply--; if (score >= beta) { //Table.Save(pos.TTKey, -1, score, TT_BETA, m); return score; } if (alpha < score) { alpha = score; bestmove = m; bound = TT_EXACT; } } //Table.Save(pos.TTKey, -1, alpha, TT_ALPHA, bestmove); //quisctime.Stop(); return alpha; }
void GameCycle::assertDraw() const { if (!isDraw()) throw BadGamePlayStateException(m_state, GAMEPLAYSTATE_DRAW); }
int Engine::AlphaBeta(int depth, int alpha, int beta, vector<Move>* variation, bool cannull, bool dopv) { #ifdef BLITZKRIEG_DEBUG Bitset tablekey = pos.PawnKey; if (alpha > beta || alpha < CONS_NEGINF || beta > CONS_INF) { cout << "info string ERROR: alpha > beta" << alpha << " " << beta << " " << ply << endl; } #endif if (isDraw()) return 0; ///Quiescence if (depth == 0) { int value = QuiescenceSearch(alpha, beta); //go to quiescence /*if (value > alpha && value < beta) PvSize = ply - 1;*/ //Table.Save(pos.TTKey,0,value,TT_EXACT,CONS_NULLMOVE); return value; } nodes++; if (nodes%CheckupNodeCount == 0) { checkup(); //nodes = 0; } ///Repetition if (ply != 0 && pos.isRepetition()) //check for repetition { //Table.Save(pos.TTKey,depth,0,TT_EXACT,CONS_NULLMOVE); return 0; } ///Probe int probe = Table.Probe(pos.TTKey, depth, alpha, beta); Move ttbestmove = createNullMove(pos.epsquare); if (probe != CONS_TTUNKNOWN) { //cout << probe << " found " << pos.TTKey << endl; if (ply != 0) { tthitcount++; return probe; } /*else { ttbestmove = Table.getBestMove(pos.TTKey); if (!ttbestmove.isNullMove()) { variation->push_back(ttbestmove); tthitcount++; return probe; } }*/ } //if (probe.avoidnull) cannull = false; int leafevalprobe = Table.Probe(pos.TTKey, 0, alpha, beta); if (leafevalprobe!=CONS_TTUNKNOWN //&& leafevalprobe.entry->bound==TT_EXACT ) { Evaluation[ply] = leafevalprobe; //use TT probe as a better leafeval } else { if (ply > 0 && currentVariation[ply] == CONS_NULLMOVE) //if last move was a nullmove, just invert score { Evaluation[ply] = -Evaluation[ply-1]; assert(!cannull); } else { Evaluation[ply] = LeafEval<false>(); } } ///Razoring if (!dopv && ply != 0 && depth < 4 && !incheck[ply] && (((Evaluation[ply] + getRazorMargin(depth)) <= alpha))) { prunednodes++; if (depth <= 1 && (Evaluation[ply] + getRazorMargin(3)) <= alpha) return QuiescenceSearch(alpha, beta); int ralpha = alpha - getRazorMargin(depth); int v = QuiescenceSearch(ralpha, ralpha + 1); if (v <= ralpha) return v; } ///Futility if (depth < 5 && ply != 0 && !incheck[ply] && ((Evaluation[ply] - getFutilityMargin(depth)) >= beta)) { futilitynodes++; return (Evaluation[ply] - getFutilityMargin(depth)); } int bound = TT_ALPHA; /*vector<Move> dummyline; dummyline.reserve(128);*/ /*vector<Move> lineptr; lineptr.reserve(128);*/ vector<Move> line; line.reserve(128); Move m; int score = 0; ///Null Move bool madenullmove = false; Bitset Pieces = pos.OccupiedSq ^ pos.Pieces[COLOR_WHITE][PIECE_PAWN] ^ pos.Pieces[COLOR_BLACK][PIECE_PAWN]; int pieceCount = popcnt(Pieces); if (cannull && !dopv && depth >= 3 && incheck[ply] == false && (pieceCount>2) //side to move does not have only pawns(to avoid zugzwang) //&& Evaluation[ply] >= beta ) { madenullmove = true; //int R = depth > 5 ? 3 : 2; //dynamic depth-based reduction int R = ((823 + 67 * depth) / 256 + std::min(max(0, Evaluation[ply] - beta) / PieceMaterial[PIECE_PAWN], 3)); m = createNullMove(pos.epsquare); ply++; #ifdef BLITZKRIEG_DEBUG Bitset ttkeynull = pos.TTKey; #endif pos.forceMove(m); /*bool fullnullmovesearch = true; if (depth >= 7) { score = -QuiescenceSearchStandPat(-beta, -beta+1); if (score < beta) fullnullmovesearch = false; } if(fullnullmovesearch)*/ score = -AlphaBeta(max(0, depth - R), -beta, -beta+1, &line, false, false); //make a null-window search (we don't care by how much it fails high, if it does) ply--; pos.unmakeMove(m); if (line.empty()!=true) Threats[ply] = line.at(line.size() - 1); #ifdef BLITZKRIEG_DEBUG if (ttkeynull != pos.TTKey) { cout << "info string ERROR: Null TT fail" << endl; _getch(); } #endif if (score >= beta) { //cout << "Null move cutoff " << beta << endl; /*if (probe.avoidnull) badavoidnull++;*/ nullcutoffs++; return score; } //if (score < alpha - 100) //score is so bad, we are in danger, so increase depth //{ // depth++; //} } //futility pruning //bool futilityprune = false; //if (depth < 4 && !underCheck && // (((leafeval + FutilityMargin[depth]) <= alpha))) //futility pruning //{ // futilitynodes++; // futilityprune = true; //} //movesort(vec,depth); bool alpharaised = false; bool foundlegal = false; Move alphamove = CONS_NULLMOVE; int finalalpha = -1; int firstalpha = -1; //vec = pos.generateMoves(); vector<Move> vec; vec.reserve(128); //movegentime.Start(); //if (futilityprune) //{ // pos.generateCaptures(vec); //search only captures in futility pruning //} //else //{ pos.generateMoves(vec); //} //movegentime.Stop(); /*vector<Move> line; line.reserve(128);*/ /*vector<int> scores; scores.reserve(128); generateCaptureScores(vec, scores);*/ if (probe==CONS_TTUNKNOWN && (dopv || Evaluation[ply] + 256 >= beta) && depth >= 2) //internal iterative deepening { int score = AlphaBeta(depth-2, alpha, beta, &line, false, dopv); } int evaldiff = ply >= 2 ? Evaluation[ply] - Evaluation[ply - 2] : 0; vector<Move> quietmoves; quietmoves.reserve(128); int bestscore = CONS_NEGINF; //int oldsortphase = SORTPHASE_NONE; for (unsigned int i = 0;i < vec.size();i++) //search { line.clear(); //dummyline.clear(); //m = vec.at(i); //int tablekey2 = pos.TTKey; m = getHighestScoringMove(vec, i); #ifdef BLITZKRIEG_DEBUG if (SortPhase == SORTPHASE_NONE) cout << "info string Sort Phase error" << endl; #endif int capturedpiece = m.getCapturedPiece(); int special = m.getSpecial(); int movingpiece = m.getMovingPiece(); int moveto = m.getTo(); int movefrom = m.getFrom(); int iscapture = isCapture(m); /*int see = 0; int evade_see = 0; Move smallestattckr = pos.getSmallestAttacker(getOpponent(pos.turn), movefrom); if (iscapture) { see = StaticExchangeEvaluation(moveto, movefrom, movingpiece, capturedpiece); } if (!smallestattckr.isNullMove()) { evade_see = StaticExchangeEvaluation(movefrom, smallestattckr.getTo(), smallestattckr.getMovingPiece(), movingpiece); }*/ //if (iscapture && depth <= 1 && see < 0) //{ //prune bad captures at low depths // continue; //} //if (depth < 8 // && !alpharaised // && noMaterialGain(m) // //&& !incheck[ply] // && !incheck[ply - 1] // && movingpiece!=PIECE_PAWN // ) //{ // if (i >= 2+depth*depth) // { // continue; // } //} if (!pos.makeMove(m)) { continue; } //if (vec.size() == 1 || (foundlegal==false && i==vec.size()-1)) //singular extension, only 1 legal move, so extend //{ // depth++; //} foundlegal = true; ply++; currentVariation[ply] = m; score = 0; int reductiondepth = 1; ///Check Extension if (pos.underCheck(pos.turn)) { incheck[ply] = true; reductiondepth--; } else { incheck[ply] = false; } ///Recapture Extension /*if (ply > 1 && m.getTo() == currentVariation[ply - 1].getTo() && iscapture && isCapture(currentVariation[ply - 1])) { reductiondepth--; }*/ //extend when capturing the last piece /*if (isCapture(m) && getSquare2Piece(capturedpiece) != PIECE_PAWN && popcnt(pos.Pieces[COLOR_WHITE][PIECE_PAWN]) + popcnt(pos.Pieces[COLOR_BLACK][PIECE_PAWN]) + 2 == popcnt(pos.OccupiedSq)) { reductiondepth -= 3; }*/ /*if (depth < 16) { if (!incheck[ply - 1] && !incheck[ply] && movingpiece != PIECE_PAWN && noMaterialGain(m)) { if(i > 3 + (1 << (depth-1))) { pos.unmakeMove(m); incheck[ply] = false; ply--; continue; } } }*/ //if (!dopv && depth < 4 && ((Evaluation[ply] + getSmallRazorMargin(depth)) <= alpha)) //small forward razoring //{ // reductiondepth++; //} ///Latemove Reduction if (!alpharaised //&& i >= 4 && depth >= 4 //&& special!=PIECE_QUEEN //&& (see < 0 || !iscapture) && SortPhase >= SORTPHASE_HISTORY //&& noMaterialGain(m) //&& (KillerMoves[0][ply].getTo() != moveto || KillerMoves[0][ply].getFrom() != movefrom) //&& (KillerMoves[1][ply].getTo() != moveto || KillerMoves[1][ply].getFrom() != movefrom) && !incheck[ply] && !incheck[ply-1] //&& (movingpiece!=PIECE_PAWN || getRank(getColorMirror(getOpponent(pos.turn), moveto))<6) //dont reduce pawn moves past 6th rank //&& m!=Threats[ply] ) { if (evaldiff > 0) reductiondepth += min(depth - 4, min((int)i,4)); else reductiondepth += min(depth - 4, min((int)i+1,5)); assert((depth - reductiondepth) >= 3); if (!dopv && HistoryScores[movingpiece][moveto] < 0) //history reduction { reductiondepth++; } if (m == Threats[ply] && reductiondepth > 0) //decrease reduction if move is a threat { reductiondepth = max(reductiondepth - 1, 0); } //if (noMaterialGain(m) && !smallestattckr.isNullMove() && evade_see < 0) //decrease reduction if move evades a capture //{ // reductiondepth = max(reductiondepth - 1, 0); //} } //if (isCapture(m) && !dopv && see > 400 && depth>=5) //prune really good captures //{ // reductiondepth += 4; //} //if (alpha_counter != 0 && (depth-reductiondepth)>=3 && i>((double)alphalast_sum/alpha_counter) && capturedpiece == SQUARE_EMPTY && special == PIECE_NONE // && !pos.underCheck(pos.turn) // && (KillerMoves[0][ply].getTo() != m.getTo() || KillerMoves[0][ply].getFrom() != m.getFrom()) // && (KillerMoves[1][ply].getTo() != m.getTo() || KillerMoves[1][ply].getFrom() != m.getFrom())) //latemove reduction //{ // reductiondepth += 2; // /*reductiondepth ++; // if (i >= 8 && depth >= 6) // { // reductiondepth++; // if (i >= 12 && depth >= 9) // reductiondepth++; // }*/ //} ///Search if(dopv && i>0 && depth>=3) //principal variation search { score = -AlphaBeta(max(depth - reductiondepth, 0), -alpha - 1, -alpha, &line, true, false); if(score > alpha && score < beta) //check for failure { line.clear(); score = -AlphaBeta(depth - 1, -beta, -alpha, &line, true, true); //research alpharaised = false; pvresearch++; //cout << "pv research" << endl; } } else { score = -AlphaBeta(max(depth - reductiondepth,0), -beta, -alpha, &line, true, dopv); //cout << "latemove" << endl; if(score > alpha && score < beta && reductiondepth>1) { line.clear(); score = -AlphaBeta(depth - 1, -beta, -alpha, &line, true, dopv); latemoveresearch++; } } currentVariation[ply] = CONS_NULLMOVE; incheck[ply] = false; ply--; pos.unmakeMove(m); assert(score > CONS_NEGINF && score < CONS_INF); assert(score >= CONS_MATED && score <= -CONS_MATED); if(score>=beta) { if(noMaterialGain(m)) { //if(Table.getBestMove(pos.TTKey)!=m) //dont store hash move as a killer setKiller(m, depth, score); int bonus = depth*depth; HistoryScores[movingpiece][m.getTo()] += bonus; if (HistoryScores[movingpiece][m.getTo()] > 200000) //prevent overflow of history values { for (int i = 0;i < 6;i++) { for (int j = 0;j < 64;j++) { HistoryScores[i][j] /= 2; } } } for (int i = 0;i < quietmoves.size();i++) { /*if(HistoryScores[quietmoves.at(i).getMovingPiece()][quietmoves.at(i).getTo()] <= bonus) HistoryScores[quietmoves.at(i).getMovingPiece()][quietmoves.at(i).getTo()] = 0; else*/ HistoryScores[quietmoves.at(i).getMovingPiece()][quietmoves.at(i).getTo()] -= bonus; } } Table.Save(pos.TTKey, depth, score, TT_BETA, m); #ifdef BLITZKRIEG_STATS betacutoff_counter++; betacutoff_sum += i+1; if (i == 0) firstbetacutoffcount++; #endif return score; //fail soft beta cutoff } else if(score>bestscore) { bestscore = score; if (score > alpha) { bound = TT_EXACT; alpha = score; alpharaised = true; alphamove = m; *variation = line; if (noMaterialGain(m)) HistoryScores[movingpiece][m.getTo()] += depth; #ifdef BLITZKRIEG_STATS if (firstalpha == -1) { firstalpha = i; } finalalpha = i; #endif } } if (noMaterialGain(m)) { quietmoves.push_back(m); } } if(!foundlegal) { //if(futilityprune) //{ // //movegentime.Start(); // vec.clear(); // pos.generateMoves(vec); // //movegentime.Stop(); // int flag = 1; // for(int i = 0;i<vec.size();i++) // { // if(pos.makeMove(m)) // { // unmakeMove(m); // flag = 0; // break; // } // } // if(flag) // { // if(pos.underCheck(pos.turn)) // { // return CONS_MATED-ply; // } // else // { // return CONS_DRAW; // } // } //} //else { if(pos.underCheck(pos.turn)) { return CONS_MATED+ply; } else { return CONS_DRAW; } } } if(!alphamove.isNullMove()) { variation->push_back(alphamove); //if(dopv) // PrincipalVariation[ply] = alphamove; /*if (depth == 1) { PvSize = ply; PvPly = ply; }*/ /*else if (ply == PvPly - 1) { PrincipalVariation[ply] = alphamove; PvPly = ply; }*/ //HistoryScores[alphamove.getFrom()][alphamove.getTo()] += depth+finalalpha; #ifdef BLITZKRIEG_STATS alpha_counter++; alphalast_sum += (finalalpha + 1); alphafirst_sum += (firstalpha + 1); #endif } Table.Save(pos.TTKey, depth, bestscore, bound, alphamove); /*if (ply == 0) { cout << "info string Stored: " << alphamove.toString() << " " << bound << " " << depth << endl; }*/ #ifdef BLITZKRIEG_DEBUG if (pos.PawnKey != tablekey) { cout << "info string ERROR: Pawn TT key doesnt match" << endl; } #endif return bestscore; }