Beispiel #1
0
int AlphaBeta(board_t *brd, int alpha, int beta, int depth, searchinfo_t *sinfo, int null)
{
	if(depth == 0){
		//return Eval(brd);
		return Quiece(brd, alpha, beta, sinfo);
	}

	if(!(sinfo->nodes & 0xfff)) CheckUp(sinfo);

	sinfo->nodes++;

	ASSERT(CheckBrd(brd));

	// if we are not the root of the tree and we have a repetition
	// or we exceeded the fifty move rule, then we have a draw and return 0
	if((IsRep(brd) || brd->fifty >= 100) && brd->ply) return 0;
	if(brd->ply >= MAXDEPTH-1) return Eval(brd);	// if we are too deep, we return

	// test if we are in check
	int check = SqAttacked(brd, LOCATEBIT(brd->bb[brd->side][King]), brd->side^1);
	if(check) depth++;

	int score = -INFINITE;
	int pvMain = NO_MOVE;
	// check the transposition table if we have searched the current position before
	// if so, return what we found
	if(TestHashTable(brd, &pvMain, &score, alpha, beta, depth)) return score;

	// Before we search, we try how we do if we don't make a move
	// i.e. make a null move
	if( null && !check && brd->ply && depth >= 4 &&
		(brd->all[brd->side]^brd->bb[brd->side][Pawn]^brd->bb[brd->side][King]) )
	{
		MakeMoveNull(brd);
		// We cannot do two null moves in a row so we set the null argument here to false
		score = -AlphaBeta(brd, -beta, -beta + 1, depth-4, sinfo, false);
		TakeBackNull(brd);

		if(sinfo->stop){
			return 0;
		}
		if(score >= beta){
			return beta;
		}
	}

	mlist_t list;
	int i;
	int legal = 0;
	int bestMove = NO_MOVE;
	int bestScore = -INFINITE;
	int oldAlpha = alpha;
	score = -INFINITE;

	GenMoves(brd, &list);

	// we tested our transposition table for the best move 'pvMain'
	// if it exists we will set this move as the first move to be searched
	if(pvMain != NO_MOVE){

		if(MakeMove(brd, pvMain)){
			score = -AlphaBeta(brd, -beta, -alpha, depth-1, sinfo, true);
			TakeBack(brd);

			bestScore = score;
			if(score > alpha){
				if(score >= beta){
					if(!(pvMain & FLAGCAP)){
						brd->betaMoves[1][brd->ply] = brd->betaMoves[0][brd->ply];
						brd->betaMoves[0][brd->ply] = pvMain;
					}
					return beta;
				}
				alpha = score;
				bestMove = pvMain;
			}
		}
		/*/
		for(i = 0; i < list.len; i++){
			if(list.move[i].move == pvMain){
				list.move[i].score = 5000000;
				break;
			}
		}//*/
	}

	for(i = 0; i < list.len; i++) // Loop through all moves
	{
		if(sinfo->stop) return 0;

		SelectNextMove(&list, i);

		if(!MakeMove(brd, list.move[i].move)) continue;

		legal++; // we have found a legal move so we need not check for mate afterwards
		// call AlphaBeta in a negamax fashion
		score = -AlphaBeta(brd, -beta, -alpha, depth-1, sinfo, true);
		TakeBack(brd);

		if(score > bestScore){
			bestScore = score;
			if(score > alpha){
				if(score >= beta){
					if(legal==1) sinfo->fhf++; 	// count the number of beta cutoffs searched first
					sinfo->fh++;				// compared to all beta cutoffs (measure of efficiency)
					if(!(list.move[i].move & FLAGCAP)){
						brd->betaMoves[1][brd->ply] = brd->betaMoves[0][brd->ply];
						brd->betaMoves[0][brd->ply] = list.move[i].move;
					}
					// Store the move in the transposition table as a beta (killer) move
					StorePvMove(brd, bestMove, depth, beta, HFBETA);
					return beta;
				}
				alpha = score;
				bestMove = list.move[i].move;
			}
		}
	}
	if(legal == 0){ // We havn't found a legal move
		if(check){
			// if we are in check it is mate; but we want the shortest path
			// to it so we'll subtract the path length
			return -MATE + brd->ply;
		}
		return 0; // Stalemate
	}

	if(oldAlpha != alpha){
		// Store exact (normal) transposition entry
		StorePvMove(brd, bestMove, depth, bestScore, HFEXACT);
	}
	else {
		// Store alpha cutoff transposition entry
		StorePvMove(brd, bestMove, depth, alpha, HFALPHA);
	}

	return alpha;
}
Beispiel #2
0
void
SelectMove(short side, SelectMove_mode iop)
{
    static short i, tempb, tempc, tempsf, tempst, xside, rpt;
    static short alpha, beta, score;
    static struct GameRec  *g;
    short sqking, in_check, blockable;

#ifdef BOOKTEST
    printf("hashbd = %ld (hashkey >> 16)|side = %d\n",
           hashbd, (hashkey >> 16)|side);
#endif

    flag.timeout = false;
    flag.back = false;
    flag.musttimeout = false;

    xside = side ^ 1;

#if ttblsz
    recycle = (GameCnt % rehash) - rehash;
#endif

    ExaminePosition(side);

    /* if background mode set to infinite */
    if (iop == BACKGROUND_MODE)
    {
        background = true;
        /* if background mode set response time to infinite */
        ResponseTime = 9999999;
    }
    else
    {
        player = side;
        SetResponseTime(side);
    }

#ifdef QUIETBACKGROUND
    if (!background)
#endif /* QUIETBACKGROUND */
        ShowResponseTime();

    ExtraTime = 0;

    score = ScorePosition(side);

#ifdef QUIETBACKGROUND
    if (!background)
#endif /* QUIETBACKGROUND */
        ShowSidetoMove();

#ifdef QUIETBACKGROUND
    if (!background)
#endif /* QUIETBACKGROUND */
        SearchStartStuff(side);

#ifdef HISTORY
    array_zero(history, sizeof_history);
#endif

    FROMsquare = TOsquare = -1;
    PV = 0;

    if (iop == FOREGROUND_MODE)
        hint = 0;

    /*
     * If the last move was the hint, select the computed answer to the
     * hint as first move to examine.
     */

#if MAXDEPTH > 3
    if (GameCnt > 0)
    {
        SwagHt = (GameList[GameCnt].gmove == PrVar[2]) ? PrVar[3] : 0;
    }
    else
#endif
        SwagHt = 0;


    for (i = 0; i < MAXDEPTH; i++)
        PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;

    /* set initial window for search */

    if (flag.tsume)
    {
        alpha =  -(SCORE_LIMIT + 999);
        beta = SCORE_LIMIT + 999;
    }
    else
    {
        alpha = score - ((computer == white) ? BAwindow : WAwindow);
        beta  = score + ((computer == white) ? BBwindow : WBwindow);
    }

    rpt = 0;
    TrPnt[1] = 0;
    root = &Tree[0];

    sqking = PieceList[side][0];
    in_check = (board[sqking] == king)
        ? SqAttacked(sqking, side^1, &blockable)
        : false;

    MoveList(side, 1, in_check, blockable);

    for (i = TrPnt[1]; i < TrPnt[2]; i++)
    {
        if (!pick(i, TrPnt[2] - 1))
            break;
    }

    /* Can I get a book move? */

    if (flag.regularstart && Book)
    {
        flag.timeout = bookflag = OpeningBook(&hint, side);

        if (TCflag)
            ResponseTime += ResponseTime;
    }

    /* Zero stats for hash table. */

    reminus = replus = 0;
    GenCnt = NodeCnt = ETnodes = EvalNodes = HashCnt
        = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0;

    globalscore = plyscore = score;
    Jscore = 0;
    zwndw = 20;


    /********************* main loop ********************************/

    Sdepth = (MaxSearchDepth < (MINDEPTH - 1))
        ? MaxSearchDepth
        : (MINDEPTH - 1);

    while (!flag.timeout)
    {
        /* go down a level at a time */
        Sdepth++;

#ifdef NULLMOVE
        null = 0;
        PVari = 1;
#endif

        /* terminate search at DepthBeyond ply past goal depth */
        if (flag.tsume)
            DepthBeyond = Sdepth;
        else
#if defined SLOW_CPU
            DepthBeyond = Sdepth + ((Sdepth == 1) ? 3 : 5);
#else
        DepthBeyond = Sdepth + ((Sdepth == 1) ? 7 : 11);
#endif

# ifdef QUIETBACKGROUND
        if (!background)
#endif /* QUIETBACKGROUND */
            ShowDepth(' ');

        /* search at this level returns score of PV */
        score = search(side, 1, Sdepth, alpha, beta, PrVar, &rpt);

        /* save PV as killer */
        for (i = 1; i <= Sdepth; i++)
            killr0[i] = PrVar[i];

        /* low search failure re-search with (-inf, score) limits  */
        if (score < alpha)
        {
            reminus++;
#ifdef QUIETBACKGROUND
            if (!background)
#endif /* QUIETBACKGROUND */
                ShowDepth('-');

            if (TCflag && TCcount < MAXTCCOUNTR)
            {
                if (hard_time_limit)
                    ExtraTime += (MAXTCCOUNTR - TCcount) * TCleft;
                else
                    ExtraTime += (8 * TCleft);

                TCcount = MAXTCCOUNTR - 1;
            }

            score = search(side, 1, Sdepth, -(SCORE_LIMIT + 999),
                           (SCORE_LIMIT + 999), PrVar, &rpt);
        }
        /* high search failure re-search with (score, +inf) limits */
        else if (score > beta && !(root->flags & exact))
        {
            replus++;
#ifdef QUIETBACKGROUND
            if (!background)
#endif /* QUIETBACKGROUND */
                ShowDepth('+');

            score = search(side, 1, Sdepth, -(SCORE_LIMIT + 999),
                           (SCORE_LIMIT + 999), PrVar, &rpt);
        }

        /**************** out of search ***********************************/
        CheckForTimeout(score, globalscore, Jscore, zwndw);

        /************************ time control ****************************/

        /* save PV as killer */
        for (i = 1; i <= Sdepth + 1; i++)
            killr0[i] = PrVar[i];

        if (!flag.timeout)
            Tscore[0] = score;

        /* if (!flag.timeout) */
        /*
          for (i = TrPnt[1] + 1; i < TrPnt[2]; i++)
          if (!pick (i, TrPnt[2] - 1))
          break;
        */

        /* if done or nothing good to look at quit */
        if ((root->flags & exact) || (score < -SCORE_LIMIT))
            flag.timeout = true;

        /* find the next best move put below root */

        if (!flag.timeout)
        {
#if !defined NODYNALPHA
            Jscore = (plyscore + score) >> 1;
#endif
            zwndw = 20 + abs(Jscore / 12);
            plyscore = score;

            /* recompute search window */
            beta = score + ((computer == white) ? BBwindow : WBwindow);
#if !defined NODYNALPHA
            alpha = ((Jscore < score) ? Jscore : score)
                - ((computer == white) ? BAwindow : WAwindow)
                - zwndw;
#else
            alpha = score - ((computer == white) ? BAwindow : WAwindow);
#endif
        }

#ifdef QUIETBACKGROUND
        if (!background)
#endif /* QUIETBACKGROUND */
            ShowResults(score, PrVar, '.');
    }
Beispiel #3
0
void GenerateAllMoves(const CHESS_BOARD *pos, MOVELIST *list) {

	ASSERT(CheckBoard(pos));

	list->count = 0;

	int pce = EMPTY;
	int side = pos->side;
	int sq = 0; int t_sq = 0;
	int pceNum = 0;
	int dir = 0;
	int index = 0;
	int pceIndex = 0;

	if (side == WHITE) {

		for (pceNum = 0; pceNum < pos->pieceNum[wP]; ++pceNum) {
			sq = pos->pList[wP][pceNum];
			ASSERT(SqOnBoard(sq));

			if (pos->pieces[sq + 10] == EMPTY) {
				AddWhitePawnMove(pos, sq, sq + 10, list);
				if (RanksBrd[sq] == RANK_2 && pos->pieces[sq + 20] == EMPTY) {
					AddQuietMove(pos, MOVE(sq, (sq + 20), EMPTY, EMPTY, MFLAGPS), list);
				}
			}

			if (!SQOFFBOARD(sq + 9) && PieceCol[pos->pieces[sq + 9]] == BLACK) {
				AddWhitePawnCapMove(pos, sq, sq + 9, pos->pieces[sq + 9], list);
			}
			if (!SQOFFBOARD(sq + 11) && PieceCol[pos->pieces[sq + 11]] == BLACK) {
				AddWhitePawnCapMove(pos, sq, sq + 11, pos->pieces[sq + 11], list);
			}

			if (pos->enPas != NO_SQ) {
				if (sq + 9 == pos->enPas) {
					AddEnPassantMove(pos, MOVE(sq, sq + 9, EMPTY, EMPTY, MFLAGEP), list);
				}
				if (sq + 11 == pos->enPas) {
					AddEnPassantMove(pos, MOVE(sq, sq + 11, EMPTY, EMPTY, MFLAGEP), list);
				}
			}
		}

		if (pos->castlePerm & WKCA) {
			if (pos->pieces[F1] == EMPTY && pos->pieces[G1] == EMPTY) {
				if (!SqAttacked(E1, BLACK, pos) && !SqAttacked(F1, BLACK, pos)) {
					AddQuietMove(pos, MOVE(E1, G1, EMPTY, EMPTY, MFLAGCA), list);
				}
			}
		}

		if (pos->castlePerm & WQCA) {
			if (pos->pieces[D1] == EMPTY && pos->pieces[C1] == EMPTY && pos->pieces[B1] == EMPTY) {
				if (!SqAttacked(E1, BLACK, pos) && !SqAttacked(D1, BLACK, pos)) {
					AddQuietMove(pos, MOVE(E1, C1, EMPTY, EMPTY, MFLAGCA), list);
				}
			}
		}

	}
	else {

		for (pceNum = 0; pceNum < pos->pieceNum[bP]; ++pceNum) {
			sq = pos->pList[bP][pceNum];
			ASSERT(SqOnBoard(sq));

			if (pos->pieces[sq - 10] == EMPTY) {
				AddBlackPawnMove(pos, sq, sq - 10, list);
				if (RanksBrd[sq] == RANK_7 && pos->pieces[sq - 20] == EMPTY) {
					AddQuietMove(pos, MOVE(sq, (sq - 20), EMPTY, EMPTY, MFLAGPS), list);
				}
			}

			if (!SQOFFBOARD(sq - 9) && PieceCol[pos->pieces[sq - 9]] == WHITE) {
				AddBlackPawnCapMove(pos, sq, sq - 9, pos->pieces[sq - 9], list);
			}

			if (!SQOFFBOARD(sq - 11) && PieceCol[pos->pieces[sq - 11]] == WHITE) {
				AddBlackPawnCapMove(pos, sq, sq - 11, pos->pieces[sq - 11], list);
			}
			if (pos->enPas != NO_SQ) {
				if (sq - 9 == pos->enPas) {
					AddEnPassantMove(pos, MOVE(sq, sq - 9, EMPTY, EMPTY, MFLAGEP), list);
				}
				if (sq - 11 == pos->enPas) {
					AddEnPassantMove(pos, MOVE(sq, sq - 11, EMPTY, EMPTY, MFLAGEP), list);
				}
			}
		}

		// castling
		if (pos->castlePerm &  BKCA) {
			if (pos->pieces[F8] == EMPTY && pos->pieces[G8] == EMPTY) {
				if (!SqAttacked(E8, WHITE, pos) && !SqAttacked(F8, WHITE, pos)) {
					AddQuietMove(pos, MOVE(E8, G8, EMPTY, EMPTY, MFLAGCA), list);
				}
			}
		}

		if (pos->castlePerm &  BQCA) {
			if (pos->pieces[D8] == EMPTY && pos->pieces[C8] == EMPTY && pos->pieces[B8] == EMPTY) {
				if (!SqAttacked(E8, WHITE, pos) && !SqAttacked(D8, WHITE, pos)) {
					AddQuietMove(pos, MOVE(E8, C8, EMPTY, EMPTY, MFLAGCA), list);
				}
			}
		}
	}

	/* Loop for slide pieces */
	pceIndex = LoopSlideIndex[side];
	pce = LoopSlidePce[pceIndex++];
	while (pce != 0) {
		ASSERT(PieceValid(pce));

		for (pceNum = 0; pceNum < pos->pieceNum[pce]; ++pceNum) {
			sq = pos->pList[pce][pceNum];
			ASSERT(SqOnBoard(sq));

			for (index = 0; index < NumDir[pce]; ++index) {
				dir = PceDir[pce][index];
				t_sq = sq + dir;

				while (!SQOFFBOARD(t_sq)) {
					// BLACK ^ 1 == WHITE       WHITE ^ 1 == BLACK
					if (pos->pieces[t_sq] != EMPTY) {
						if (PieceCol[pos->pieces[t_sq]] == (side ^ 1)) {
							AddCaptureMove(pos, MOVE(sq, t_sq, pos->pieces[t_sq], EMPTY, 0), list);
						}
						break;
					}
					AddQuietMove(pos, MOVE(sq, t_sq, EMPTY, EMPTY, 0), list);
					t_sq += dir;
				}
			}
		}

		pce = LoopSlidePce[pceIndex++];
	}

	/* Loop for non slide */
	pceIndex = LoopNonSlideIndex[side];
	pce = LoopNonSlidePce[pceIndex++];

	while (pce != 0) {
		ASSERT(PieceValid(pce));

		for (pceNum = 0; pceNum < pos->pieceNum[pce]; ++pceNum) {
			sq = pos->pList[pce][pceNum];
			ASSERT(SqOnBoard(sq));

			for (index = 0; index < NumDir[pce]; ++index) {
				dir = PceDir[pce][index];
				t_sq = sq + dir;

				if (SQOFFBOARD(t_sq)) {
					continue;
				}

				// BLACK ^ 1 == WHITE       WHITE ^ 1 == BLACK
				if (pos->pieces[t_sq] != EMPTY) {
					if (PieceCol[pos->pieces[t_sq]] == (side ^ 1)) {
						AddCaptureMove(pos, MOVE(sq, t_sq, pos->pieces[t_sq], EMPTY, 0), list);
					}
					continue;
				}
				AddQuietMove(pos, MOVE(sq, t_sq, EMPTY, EMPTY, 0), list);
			}
		}

		pce = LoopNonSlidePce[pceIndex++];
	}

	//ASSERT(MoveListOk(list, pos));
}