/* * We always try the maximize the board value */ int Board::search(int depth, int alpha, int beta) { int actValue= -14999+depth, value; Move m; MoveList list; bool depthPhase, doDepthSearch; searchCalled++; /* We make a depth search for the following move types... */ int maxType = (depth < maxDepth-1) ? Move::maxMoveType() : (depth < maxDepth) ? Move::maxPushType() : Move::maxOutType(); generateMoves(list); #ifdef MYTRACE int oldRatedPositions; int oldWonPositions; int oldSearchCalled; int oldMoveCount; int oldNormalCount; int oldPushCount; int oldOutCount; int oldCutoffCount; spyDepth = depth; moveCount += list.getLength(); /* if (spyLevel>1) { indent(depth); qDebug("%s (%6d .. %6d) MaxType %s\n", depth, (color==color1)?"O":"X", alpha,beta, (depth < maxDepth-1) ? "Moving" : (depth < maxDepth)? "Pushing" : "PushOUT" ); } */ #endif /* check for a old best move in main combination */ if (inPrincipalVariation) { m = pv[depth]; if ((m.type != Move::none) && (!list.isElement(m, 0, true))) m.type = Move::none; if (m.type == Move::none) inPrincipalVariation = false; #ifdef MYTRACE else { if (spyLevel>1) { indent(spyDepth); qDebug("Got from pv !\n" ); } } #endif } // first, play all moves with depth search depthPhase = true; while (1) { // get next move if (m.type == Move::none) { if (depthPhase) depthPhase = list.getNext(m, maxType); if (!depthPhase) if (!list.getNext(m, Move::none)) break; } // we could start with a non-depth move from principal variation doDepthSearch = depthPhase && (m.type <= maxType); #ifdef MYTRACE if (m.isOutMove()) outCount++; else if (m.isPushMove()) pushCount++; else normalCount++; if (doDepthSearch) { oldRatedPositions = ratedPositions; oldWonPositions = wonPositions; oldSearchCalled = searchCalled; oldMoveCount = moveCount; oldNormalCount = normalCount; oldPushCount = pushCount; oldOutCount = outCount; oldCutoffCount = cutoffCount; if (spyLevel>1) { indent(spyDepth); qDebug("%s [%6d .. %6d] ", (color==color1)?"O":"X", alpha,beta); m.print(); qDebug("\n"); } #ifdef SPION if (bUpdateSpy) emit update(depth, 0, m, false); #endif } #endif playMove(m); if (!isValid()) { /* Possibility (1) to win: Piece Count <9 */ value = 14999-depth; // value = ((depth < maxDepth) ? 15999:14999) - depth; #ifdef MYTRACE wonPositions++; #endif } else { if (doDepthSearch) { /* opponent searches for his maximum; but we want the * minimum: so change sign (for alpha/beta window too!) */ value = - search(depth+1,-beta,-alpha); } else { ratedPositions++; value = calcEvaluation(); } } takeBack(); /* For GUI response */ if (doDepthSearch && (maxDepth - depth >2)) emit searchBreak(); #ifdef MYTRACE if (doDepthSearch) { spyDepth = depth; if (spyLevel>1) { indent(spyDepth); if (oldSearchCalled < searchCalled) { qDebug(" %d Calls", searchCalled-oldSearchCalled); if (cutoffCount>oldCutoffCount) qDebug(" (%d Cutoffs)", cutoffCount-oldCutoffCount); qDebug(", GenMoves %d (%d/%d/%d played)", moveCount - oldMoveCount, normalCount - oldNormalCount, pushCount-oldPushCount, outCount-oldOutCount); qDebug(", Rate# %d", ratedPositions+wonPositions - oldRatedPositions - oldWonPositions); if (wonPositions > oldWonPositions) qDebug(" (%d Won)", wonPositions- oldWonPositions); qDebug("\n"); indent(spyDepth); } qDebug(" => Rated %d%s\n", value, (value>14900) ? ", WON !": (value>=beta) ? ", CUTOFF !": (value>actValue) ? ", Best !": ""); } } else { if (spyLevel>2) { indent(spyDepth); qDebug("%s (%6d .. %6d) %-25s => Rating %6d%s\n", (color==color1)?"O":"X", alpha,beta, m.name().toLatin1(), value, (value>14900) ? ", WON !": (value>=beta) ? ", CUTOFF !": (value>actValue) ? ", Best !": ""); } } if (value>=beta) cutoffCount++; #endif #ifdef SPION if (bUpdateSpy) { if (value > actValue) emit updateBest(depth, value, m, value >= beta); emit update(depth, value, m, true); } #endif if (value > actValue) { actValue = value; pv.update(depth, m); // Only update best move if not stopping search if (!breakOut && (depth == 0)) { _bestMove = m; if (bUpdateSpy) { emit updateBestMove(m, actValue); #ifdef MYTRACE if (spyLevel>0) { int i; qDebug("> New pv (Rating %d):", actValue); for(i=0;i<=maxDepth;i++) { qDebug("\n> D %d: %s", i, pv[i].name().toLatin1() ); } qDebug("\n>\n"); } #endif } } if (actValue>14900 || actValue >= beta) return actValue; /* maximize alpha */ if (actValue > alpha) alpha = actValue; } if (breakOut) depthPhase=false; m.type = Move::none; } return actValue; }
/* * We always try the maximize the board value */ int Board::search(int depth, int alpha, int beta) { int actValue=-16000, value; Move m; MoveList list; bool stop = false; /* We make a depth search for the following move types... */ int maxType = (depth < maxDepth/2) ? Move::maxMoveType() : (depth < maxDepth) ? Move::maxPushType() : Move::maxOutType(); generateMoves(list); #ifdef MYTRACE printf(">>>>>>>> Depth %d\n", depth); #endif /* check for a old best move in main combination */ if (inMainCombination) { m = mc[depth]; if (!list.isElement(m, 0)) m.type = Move::none; if (m.type == Move::none) inMainCombination = false; if (m.type > maxType) m.type = Move::none; } if (m.type == Move::none) stop = !list.getNext(m, maxType); /* depth first search */ while(!stop) { #ifdef MYTRACE indent(depth); m.print(); printf("\n"); #endif #ifdef SPION if (bUpdateSpy) emit update(depth, 0, m, false); #endif playMove(m); if (!isValid()) value = ((depth < maxDepth) ? 15999:14999) - depth; else { /* opponent searches for his maximum; but we won't the * minimum: so change sign (for alpha/beta window too!) */ value = - search(depth+1,-beta,-alpha); } takeBack(); /* For GUI response */ if (maxDepth - depth >2) emit searchBreak(); #ifdef MYTRACE indent(depth); printf("=> (%d - %d): Value %d [ %d ] for ", alpha, beta, value,actValue); m.print(); printf("\n"); #endif #ifdef SPION if (bUpdateSpy) { if (value > actValue) emit updateBest(depth, value, m, value >= beta); emit update(depth, value, m, true); } #endif if (value > actValue) { actValue = value; mc.update(depth, m); if (bUpdateSpy && depth == 0) emit updateBestMove(m, actValue); if (actValue >= beta) { #ifdef MYTRACE indent(depth); printf("CUTOFF\n"); #endif return actValue; } if (actValue > alpha) alpha = actValue; } stop = (!list.getNext(m, maxType)) || breakOut; } /* other moves: calculate rating */ while(list.getNext(m, Move::none)) { playMove(m); if (!isValid()) value = ((depth < maxDepth) ? 15999:14999) - depth; else value = calcValue(); takeBack(); #ifdef SPION if (bUpdateSpy) { if (value > actValue) emit updateBest(depth, value, m, value >= beta); emit update(depth, value, m, true); } #endif #ifdef MYTRACE indent(depth); printf("> (%d - %d): Value %d [ %d ] for ", alpha, beta, value, actValue); m.print(); printf("\n"); #endif if (value > actValue) { actValue = value; mc.update(depth, m); if (actValue >= beta) { #ifdef MYTRACE indent(depth); printf("CUTOFF\n"); #endif break; } if (actValue > alpha) alpha = actValue; } } return actValue; }