Esempio n. 1
0
static void DoMove(struct resRes *menuData, MENUITEM *item, MENUITEM *dest)
{
    if (item != dest)
    {
        MENUITEM **itemplace = GetItemPlace(&menuData->resource->u.menu->items, item);
        MENUITEM **destplace;
        if (dest)
        {
            destplace = GetItemPlace(&menuData->resource->u.menu->items, dest);
        }
        else
        {
            destplace = itemplace;
            while (*destplace)
                destplace = &(*destplace)->next;
        }
        if (itemplace && destplace)
        {
            UndoMove(menuData, itemplace, item);
            *itemplace = (*itemplace)->next;
            item->next = *destplace;
            *destplace = item;
            ResSetDirty(menuData);
            InvalidateRect(menuData->activeHwnd, 0, FALSE);
        }
    }
}
void DfpnSolver::LookupChildDataNonConst(SgMove move, DfpnData& data)
{
    PlayMove(move);
    if (! TTRead(data))
    {
        data.m_bounds.phi = 1;
        data.m_bounds.delta = 1;
        data.m_work = 0;
    }
    UndoMove();
}
Esempio n. 3
0
File: game.c Progetto: zhu-jz/turtle
void UndoGameMove(GAME *Game) {

   if (Game->MoveNo == 0) {
      Error("Game->MoveNo == 0 in UndoGameMove()");
      return;
   }

   Game->MoveNo--;
   UndoMove(Game->Board,Game->Move[Game->MoveNo].Move);
   if (RestoreClocks) ElapsedTime[Game->Board->Colour>0] -= Game->Move[Game->MoveNo].Time;

   TurnBegin = CurrentTime();
}
void DfpnSolver::GetPVFromHash(PointSequence& pv)
{
    // to do: SgAssertRestore r(state of search in subclass);
    int nuMoves = 0;
    for (;; ++nuMoves) 
    {
        DfpnData data;
        if (  ! TTRead(data)
           || data.m_bestMove == SG_NULLMOVE
           )
            break;
        pv.push_back(data.m_bestMove);
        PlayMove(data.m_bestMove);
    }
    while (--nuMoves >= 0)
    	UndoMove();
}
Esempio n. 5
0
void GameTree::PrintGame(FILE* f){
    int i;
    char pre[100];
    for(i=0;i<currDepth;i++) pre[i]=' ';
    sprintf(pre+i, "%3ld %2d", currIdx, currDepth);
    
    if(currIdx==0){
        fprintf(f,"Size=%zu\n",size);
        fprintf(f,"%s %d %d %0.1f\n",pre,MoveValue(),val,IsWin());
    }else{
        fprintf(f,"%s %d %d %0.1f\n",pre,MoveValue(),val,IsWin());
    }
    if(currDepth<depth)
        for(int i=0;i<breath;i++){
            DoMove(i);
            PrintGame(f);
            UndoMove();
        }
}
bool DfpnSolver::Validate(DfpnHashTable& hashTable, const SgBlackWhite winner,
                          SgSearchTracer& tracer)
{
    SG_ASSERT_BW(winner);
    DfpnData data;
    if (! TTRead(data))
    {
        PointSequence pv;
        StartSearch(hashTable, pv);
        const bool wasRead = TTRead(data);
        SG_DEBUG_ONLY(wasRead);
        SG_ASSERT(wasRead);
    }

    const bool orNode = (winner == GetColorToMove());
    if (orNode)
    {
        if (! data.m_bounds.IsWinning())
        {
            SgWarning() << "OR not winning. DfpnData:" << data << std::endl;
            return false;
        }
    }
    else // AND node
    {
        if (! data.m_bounds.IsLosing())
        {
            SgWarning() << "AND not losing. DfpnData:" << data << std::endl;
            return false;
        }
	}

    SgEmptyBlackWhite currentWinner;
    if (TerminalState(GetColorToMove(), currentWinner))
    {
        if (winner == currentWinner)
            return true;
        else
        {
            SgWarning() << "winner disagreement: " 
                << SgEBW(winner) << ' ' << SgEBW(currentWinner) 
                << std::endl;
            return false;
        }
    }

    std::vector<SgMove> moves;
    if (orNode)
        moves.push_back(data.m_bestMove);
    else // AND node
        GenerateChildren(moves);

    // recurse
    for (std::vector<SgMove>::const_iterator it = moves.begin();
         it != moves.end(); ++it)
    {
        tracer.AddTraceNode(*it, GetColorToMove());
        PlayMove(*it);
        if (! Validate(hashTable, winner, tracer))
            return false;
        UndoMove();
        tracer.TakeBackTraceNode();
    }
    return true;
}
size_t DfpnSolver::MID(const DfpnBounds& maxBounds, DfpnHistory& history)
{
    maxBounds.CheckConsistency();
    SG_ASSERT(maxBounds.phi > 1);
    SG_ASSERT(maxBounds.delta > 1);

    ++m_numMIDcalls;
    size_t prevWork = 0;
    SgEmptyBlackWhite colorToMove = GetColorToMove();

    DfpnData data;
    if (TTRead(data)) 
    {
        prevWork = data.m_work;
        if (! maxBounds.GreaterThan(data.m_bounds))
            // Estimated bounds are larger than we had
            // anticipated. The calling state must have computed
            // the max bounds with out of date information, so just
            // return here without doing anything: the caller will
            // now update to this new info and carry on.
            return 0;
    }
    else
    {
        SgEmptyBlackWhite winner = SG_EMPTY;
        if (TerminalState(colorToMove, winner))
        {
            ++m_numTerminal;
            DfpnBounds terminal;
            if (colorToMove == winner)
                DfpnBounds::SetToWinning(terminal);
            else
            {
                SG_ASSERT(SgOppBW(colorToMove) == winner);
                DfpnBounds::SetToLosing(terminal);
            }
            TTWrite(DfpnData(terminal, SG_NULLMOVE, 1));
            return 1;
        }
    }
    
    ++m_generateMoves;
    DfpnChildren children;
    GenerateChildren(children.Children());

    // Not thread safe: perhaps move into while loop below later...
    std::vector<DfpnData> childrenData(children.Size());
    for (size_t i = 0; i < children.Size(); ++i)
        LookupData(childrenData[i], children, i);
    // Index used for progressive widening
    size_t maxChildIndex = ComputeMaxChildIndex(childrenData);

    SgHashCode currentHash = Hash();
    SgMove bestMove = SG_NULLMOVE;
    DfpnBounds currentBounds;
    size_t localWork = 1;
    do
    {
        UpdateBounds(currentBounds, childrenData, maxChildIndex);
        if (! maxBounds.GreaterThan(currentBounds))
            break;

        // Select most proving child
        std::size_t bestIndex = 999999;
        DfpnBoundType delta2 = DfpnBounds::INFTY;
        SelectChild(bestIndex, delta2, childrenData, maxChildIndex);
        bestMove = children.MoveAt(bestIndex);

        // Compute maximum bound for child
        const DfpnBounds childBounds(childrenData[bestIndex].m_bounds);
        DfpnBounds childMaxBounds;
        childMaxBounds.phi = maxBounds.delta 
            - (currentBounds.delta - childBounds.phi);
        childMaxBounds.delta = delta2 == DfpnBounds::INFTY ? maxBounds.phi :
            std::min(maxBounds.phi,
                     std::max(delta2 + 1, DfpnBoundType(delta2 * (1.0 + m_epsilon))));
        SG_ASSERT(childMaxBounds.GreaterThan(childBounds));
        if (delta2 != DfpnBounds::INFTY)
            m_deltaIncrease.Add(float(childMaxBounds.delta-childBounds.delta));

        // Recurse on best child
        PlayMove(bestMove);
        history.Push(bestMove, currentHash);
        localWork += MID(childMaxBounds, history);
        history.Pop();
        UndoMove();

        // Update bounds for best child
        LookupData(childrenData[bestIndex], children, bestIndex);

        // Compute some stats when find winning move
        if (childrenData[bestIndex].m_bounds.IsLosing())
        {
            m_moveOrderingIndex.Add(float(bestIndex));
            m_moveOrderingPercent.Add(float(bestIndex) 
                                      / (float)childrenData.size());
            m_totalWastedWork += prevWork + localWork
                - childrenData[bestIndex].m_work;
        }
        else if (childrenData[bestIndex].m_bounds.IsWinning())
            maxChildIndex = ComputeMaxChildIndex(childrenData);

    } while (! CheckAbort());

    // Find the most delaying move for losing states, and the smallest
    // winning move for winning states.
    if (currentBounds.IsSolved())
    {
        if (currentBounds.IsLosing())
        {
            std::size_t maxWork = 0;
            for (std::size_t i = 0; i < children.Size(); ++i)
            {
                if (childrenData[i].m_work > maxWork)
                {
                    maxWork = childrenData[i].m_work;
                    bestMove = children.MoveAt(i);
                }
            }
        }
        else
        {
            std::size_t minWork = DfpnBounds::INFTY;
            for (std::size_t i = 0; i < children.Size(); ++i)
            {
                if (childrenData[i].m_bounds.IsLosing() 
                    && childrenData[i].m_work < minWork)
                {
                    minWork = childrenData[i].m_work;
                    bestMove = children.MoveAt(i);
                }
            }
        }
    }
    
    // Store search results
    TTWrite(DfpnData(currentBounds, bestMove, localWork + prevWork));
    return localWork;
}
Esempio n. 8
0
static int negascout(struct SearchData *sd,
                     int alpha,
                     int beta,
                     const int depth,
                     int node_type
#if MP
                     ,int exclusiveP
#endif /* MP  */
                    ) {
    struct Position *p = sd->position;
    struct SearchStatus *st;
    int best = -INF;
    int bestm = M_NONE;
    int tmp;
    int talpha;
    int incheck;
    int lmove;
    int move;
    int extend = 0;
    int threat = FALSE;
    int reduce_extensions;
    int next_type;
    int was_futile = FALSE;
#if FUTILITY
    int is_futile;
    int optimistic = 0;
#endif

#if MP
    int deferred_cnt = 0;
    int deferred_list[MAX_DEFERRED];
    int deferred_depth[MAX_DEFERRED];
#endif

    EnterNode(sd);

    Nodes++;

    /* check for search termination */
    if (sd->master && TerminateSearch(sd)) {
        AbortSearch = TRUE;
        goto EXIT;
    }

    /* max search depth reached */
    if (sd->ply >= MaxDepth) goto EXIT;

    /*
     * Check for insufficent material or theoretical draw.
     */

    if ( /* InsufMat(p) || CheckDraw(p) || */  Repeated(p, FALSE)) {
        best = 0;
        goto EXIT;
    }

    /*
     * check extension
     */

    incheck = InCheck(p, p->turn);
    if (incheck && p->material[p->turn] > 0) {
        extend += CheckExtend(p);
        ChkExt++;
    }

    /*
     * Check the hashtable
     */

    st = sd->current;

    HTry++;
#if MP
    switch (ProbeHT(p->hkey, &tmp, depth, &(st->st_hashmove), &threat, sd->ply,
                    exclusiveP, sd->localHashTable))
#else
    switch (ProbeHT(p->hkey, &tmp, depth, &(st->st_hashmove), &threat, sd->ply))
#endif /* MP */
    {
    case ExactScore:
        HHit++;
        best = tmp;
        goto EXIT;
    case UpperBound:
        if (tmp <= alpha) {
            HHit++;
            best = tmp;
            goto EXIT;
        }
        break;
    case LowerBound:
        if (tmp >= beta) {
            HHit++;
            best = tmp;
            goto EXIT;
        }
        break;
    case Useless:
        threat = !incheck && MateThreat(p, OPP(p->turn));
        break;
#if MP
    case OnEvaluation:
        best = -ON_EVALUATION;
        goto EXIT;
#endif
    }

    /*
     * Probe EGTB
     */

    if (depth > EGTBDepth && ProbeEGTB(p, &tmp, sd->ply)) {
        best = tmp;
        goto EXIT;
    }

    /*
     * Probe recognizers
     */

    switch (ProbeRecognizer(p, &tmp)) {
    case ExactScore:
        best = tmp;
        goto EXIT;
    case LowerBound:
        if (tmp >= beta) {
            best = tmp;
            goto EXIT;
        }
        break;
    case UpperBound:
        if (tmp <= alpha) {
            best = tmp;
            goto EXIT;
        }
        break;
    }

#if NULLMOVE

    /*
     * Null move search.
     * See Christian Donninger, "Null Move and Deep Search"
     * ICCA Journal Volume 16, No. 3, pp. 137-143
     */

    if (!incheck && node_type == CutNode && !threat) {
        int next_depth;
        int nms;

        next_depth = depth - ReduceNullMove;

        if (next_depth > 0) {
            next_depth = depth - ReduceNullMoveDeep;
        }

        DoNull(p);
        if (next_depth < 0) {
            nms = -quies(sd, -beta, -beta+1, 0);
        } else {
#if MP
            nms = -negascout(sd, -beta, -beta+1, next_depth, AllNode, 0);
#else
            nms = -negascout(sd, -beta, -beta+1, next_depth, AllNode);
#endif
        }
        UndoNull(p);

        if (AbortSearch) goto EXIT;
        if (nms >= beta) {
            if (p->nonPawn[p->turn] >= Value[Queen]) {
                best = nms;
                goto EXIT;
            } else {
                if (next_depth < 0) {
                    nms = quies(sd, beta-1, beta, 0);
                } else {
#if MP
                    nms = negascout(sd, beta-1, beta, next_depth, CutNodeNoNull,
                                    0);
#else
                    nms = negascout(sd, beta-1, beta, next_depth,
                                    CutNodeNoNull);
#endif
                }

                if (nms >= beta) {
                    best = nms;
                    goto EXIT;
                } else {
                    extend += ExtendZugzwang;
                    ZZExt++;
                }
            }
        } else if (nms <= -CMLIMIT) {
            threat = TRUE;
        }
    }
#endif /* NULLMOVE */

    lmove = (p->actLog-1)->gl_Move;
    reduce_extensions = (sd->ply > 2*sd->depth);
    talpha = alpha;

    switch (node_type) {
    case AllNode:
        next_type = CutNode;
        break;
    case CutNode:
    case CutNodeNoNull:
        next_type = AllNode;
        break;
    default:
        next_type = PVNode;
        break;
    }

#if FUTILITY
    is_futile = !incheck && !threat && alpha < CMLIMIT && alpha > -CMLIMIT;
    if (is_futile) {
        if (p->turn == White) {
            optimistic = MaterialBalance(p) + MaxPos;
        } else {
            optimistic = -MaterialBalance(p) + MaxPos;
        }
    }
#endif /* FUTILITY */

    /*
     * Internal iterative deepening. If we do not have a move, we try
     * a shallow search to find a good candidate.
     */

    if (depth > 2*OnePly && ((alpha + 1) != beta) && !LegalMove(p, st->st_hashmove)) {
        int useless;
#if MP
        useless = negascout(sd, alpha, beta, depth-2*OnePly, PVNode, 0);
#else
        useless = negascout(sd, alpha, beta, depth-2*OnePly, PVNode);
#endif
        st->st_hashmove = sd->pv_save[sd->ply+1];
    }

    /*
     * Search all legal moves
     */

    while ((move = incheck ? NextEvasion(sd) : NextMove(sd)) != M_NONE) {
        int next_depth = extend;

        if (move & M_CANY && !MayCastle(p, move)) continue;

        /*
         * recapture extension
         */

        if ((move & M_CAPTURE) && (lmove & M_CAPTURE) &&
                M_TO(move) == M_TO(lmove) &&
                IsRecapture(p->piece[M_TO(move)], (p->actLog-1)->gl_Piece)) {
            RCExt += 1;
            next_depth += ExtendRecapture[TYPE(p->piece[M_TO(move)])];
        }

        /*
         * passed pawn push extension
         */

        if (TYPE(p->piece[M_FROM(move)]) == Pawn &&
                p->nonPawn[OPP(p->turn)] <= Value[Queen]) {

            int to = M_TO(move);

            if (((p->turn == White && to >= a7)
                    || (p->turn == Black && to <= h2))
                    && IsPassed(p, to, p->turn) && SwapOff(p, move) >= 0) {
                next_depth += ExtendPassedPawn;
                PPExt += 1;
            }
        }

        /*
         * limit extensions to sensible range.
         */

        if (reduce_extensions) next_depth /= 2;

        next_depth += depth - OnePly;

#if FUTILITY

        /*
         * Futility cutoffs
         */

        if (is_futile) {
            if (next_depth < 0 && !IsCheckingMove(p, move)) {
                tmp = optimistic + ScoreMove(p, move);
                if (tmp <= alpha) {
                    if (tmp > best) {
                        best = tmp;
                        bestm = move;
                        was_futile = TRUE;
                    }
                    continue;
                }
            }
#if EXTENDED_FUTILITY

            /*
             * Extended futility cutoffs and limited razoring.
             * See Ernst A. Heinz, "Extended Futility Pruning"
             * ICCA Journal Volume 21, No. 2, pp 75-83
             */

            else if (next_depth >= 0 && next_depth < OnePly
                     && !IsCheckingMove(p, move)) {
                tmp = optimistic + ScoreMove(p, move) + (3*Value[Pawn]);
                if (tmp <= alpha) {
                    if (tmp > best) {
                        best = tmp;
                        bestm = move;
                        was_futile = TRUE;
                    }
                    continue;
                }
            }
#if RAZORING
            else if (next_depth >= OnePly && next_depth < 2*OnePly
                     && !IsCheckingMove(p, move)) {
                tmp = optimistic + ScoreMove(p, move) + (6*Value[Pawn]);
                if (tmp <= alpha) {
                    next_depth -= OnePly;
                }
            }
#endif /* RAZORING */
#endif /* EXTENDED_FUTILITY */
        }

#endif /* FUTILITY */

        DoMove(p, move);
        if (InCheck(p, OPP(p->turn))) {
            UndoMove(p, move);
        } else {
            /*
             * Check extension
             */

            if (p->material[p->turn] > 0 && InCheck(p, p->turn)) {
                next_depth += (reduce_extensions) ?
                              ExtendInCheck>>1 : ExtendInCheck;
            }

            /*
             * Recursively search this position. If depth is exhausted, use
             * quies, otherwise use negascout.
             */

            if (next_depth < 0) {
                tmp = -quies(sd, -beta, -talpha, 0);
            } else if (bestm != M_NONE && !was_futile) {
#if MP
                tmp = -negascout(sd, -talpha-1, -talpha, next_depth, next_type,
                                 bestm != M_NONE);
                if (tmp != ON_EVALUATION && tmp > talpha && tmp < beta) {
                    tmp = -negascout(sd, -beta, -tmp, next_depth,
                                     node_type == PVNode ? PVNode : AllNode,
                                     bestm != M_NONE);
                }
#else
                tmp = -negascout(sd, -talpha-1, -talpha, next_depth, next_type);
                if (tmp > talpha && tmp < beta) {
                    tmp = -negascout(sd, -beta, -tmp, next_depth,
                                     node_type == PVNode ? PVNode : AllNode);
                }
#endif /* MP */
            } else {
#if MP
                tmp = -negascout(sd, -beta, -talpha, next_depth, next_type,
                                 bestm != M_NONE);
#else
                tmp = -negascout(sd, -beta, -talpha, next_depth, next_type);
#endif /* MP */
            }

            UndoMove(p, move);

            if (AbortSearch) goto EXIT;

#if MP
            if (tmp == ON_EVALUATION) {

                /*
                 * This child is ON_EVALUATION. Remember move and
                 * depth.
                 */

                deferred_list[deferred_cnt] = move;
                deferred_depth[deferred_cnt] = next_depth;
                deferred_cnt++;

            } else {
#endif /* MP */

                /*
                 * beta cutoff, enter move in Killer/Countermove table
                 */

                if (tmp >= beta) {
                    if (!(move & M_TACTICAL)) {
                        PutKiller(sd, move);
                        sd->counterTab[p->turn][lmove & 4095] = move;
                    }
                    StoreResult(sd, tmp, alpha, beta, move, depth, threat);
                    best = tmp;
                    goto EXIT;
                }

                /*
                 * Improvement on best move to date
                 */

                if (tmp > best) {
                    best = tmp;
                    bestm = move;
                    was_futile = FALSE;

                    if (best > talpha) {
                        talpha = best;
                    }
                }

                next_type = CutNode;
#if MP
            }
#endif /* MP */
        }
    }
Esempio n. 9
0
static int quies(struct SearchData *sd, int alpha, int beta, int depth) {
    struct Position *p = sd->position;
    int best;
    int move;
    int talpha;
    int tmp;
    QNodes++;

    EnterNode(sd);

    /* max search depth reached */
    if (sd->ply >= MaxDepth || Repeated(p, FALSE)) {
        best = 0;
        goto EXIT;
    }

    /*
     * Probe recognizers. If the probe is successful, use the
     * recognizer score as evaluation score.
     *
     * Otherwise, use ScorePosition()
     */

    switch (ProbeRecognizer(p, &tmp)) {
    case ExactScore:
        best = tmp;
        goto EXIT;
    case LowerBound:
        best = tmp;
        if (best >= beta) {
            goto EXIT;
        }
        break;
    case UpperBound:
        best = tmp;
        if (best <= alpha) {
            goto EXIT;
        }
        break;
    default:
        best = ScorePosition(p, alpha, beta);
        break;
    }

    if (best >= beta) {
        goto EXIT;
    }

    talpha = MAX(alpha, best);

    while ((move = NextMoveQ(sd, alpha) ) != M_NONE) {
        DoMove(p, move);
        if (InCheck(p, OPP(p->turn))) UndoMove(p, move);
        else {
            tmp = -quies(sd, -beta, -talpha, depth-1);
            UndoMove(p, move);
            if (tmp >= beta) {
                best = tmp;
                goto EXIT;
            }
            if (tmp > best) {
                best = tmp;
                if (best > talpha) {
                    talpha = best;
                }
            }
        }
    }

EXIT:

    LeaveNode(sd);
    return best;
}
Esempio n. 10
0
static void Undo(char *args)
{
    if(CurrentPosition->ply > 0) {
        UndoMove(CurrentPosition, (CurrentPosition->actLog-1)->gl_Move);
    }
}