예제 #1
0
        public virtual int AlphaBeta(Position p, int depth, int alpha, int beta, double extension, MoveList pv, long Zkey, int move)
        {

            if (nodecount[1] + nodecount[0] > NODELIMIT)  //wenn Knotenlimit überschritten, gehe zu Exception
            {
                throw new TooManyNodesException();
            }

            if (depth < maxDepth)
            {
                maxDepth = depth;
            }

            p.makeMove(move);
            nodecount[0] += 1;
            int hashflag = HASHALPHA;

            //letzte Bits des Keys in Index umwandeln
            int index = (int)Zkey & (HASHSIZE - 1);

            //Hash Tables
            hvalue = -1;
            bestMove = -1;
            newbeta = beta;
            newalpha = alpha;
            if (HashTable2[index].key == Zkey)
            {
                if (HashTable2[index].depth >= (depth + extension))
                {
                    if (HashTable2[index].flag == HASHEXACT)
                    {
                        hvalue = HashTable2[index].value_Renamed;
                    }
                    if (HashTable2[index].flag == HASHALPHA && HashTable2[index].value_Renamed <= alpha)
                    {
                        hvalue = alpha;
                    }
                    if (HashTable2[index].flag == HASHALPHA && HashTable2[index].value_Renamed < beta)
                    {
                        newbeta = HashTable2[index].value_Renamed;
                    }
                    if (HashTable2[index].flag == HASHBETA && HashTable2[index].value_Renamed >= beta)
                    {
                        hvalue = beta;
                    }
                    if (HashTable2[index].flag == HASHBETA && HashTable2[index].value_Renamed > alpha)
                    {
                        newalpha = HashTable2[index].value_Renamed;
                    }
                }

                bestMove = HashTable2[index].move;
            }
            if (HashTable1[index].key == Zkey)
            {
                if (HashTable1[index].depth >= (depth + extension))
                {
                    if (HashTable1[index].flag == HASHEXACT)
                    {
                        hvalue = HashTable1[index].value_Renamed;
                    }
                    if (HashTable1[index].flag == HASHALPHA && HashTable1[index].value_Renamed <= alpha)
                    {
                        hvalue = alpha;
                    }
                    if (HashTable1[index].flag == HASHALPHA && HashTable1[index].value_Renamed < beta)
                    {
                        newbeta = HashTable1[index].value_Renamed;
                    }
                    if (HashTable1[index].flag == HASHBETA && HashTable1[index].value_Renamed >= beta)
                    {
                        hvalue = beta;
                    }
                    if (HashTable1[index].flag == HASHBETA && HashTable1[index].value_Renamed > alpha)
                    {
                        newalpha = HashTable1[index].value_Renamed;
                    }
                }
                bestMove = HashTable1[index].move;
            }
            if (HashTable3[index].key == Zkey)
            {
                hvalue = HashTable3[index].value_Renamed;
            }
            beta = newbeta;
            alpha = newalpha;
            if (hvalue != -1)
            {
                pv.length = 0;
                return hvalue;
            }

            MoveList mypv = new MoveList();

            //entschiedene Positionen
            if (p.isWon(!p.toMove, move))
            {
                pv.length = 0;
                addHashEntries(Zkey, index, depth + extension, -1000 + p.numberOfDiscs(), HASHEXACT, -1);
                return -1000 + p.numberOfDiscs();
            }

            if (p.Draw)
            {
                pv.length = 0;
                addHashEntries(Zkey, index, depth + extension, 0, HASHEXACT, -1);
                return 0;
            }

            //Eröffnungsbuchzugriff
            if (opening)
            {
                if (p.numberOfDiscs() <= 8)
                {
                    value_Renamed = searchBook(p);
                    if (value_Renamed != -1)
                    {
                        pv.length = 0;
                        addHashEntries(Zkey, index, depth + extension, value_Renamed, HASHEXACT, -1);
                        return value_Renamed;
                    }
                }
            }

            //Interior Node Recognition
            firstFreeColumn = -1;
            secondFreeColumn = -1;
            freeColumns = 0;
            for (int i = 0; i < 7; i++)
            {
                if (p.height[i] != 6)
                {
                    freeColumns += 1;
                    if (freeColumns == 3)
                        break;
                    if (freeColumns == 1)
                        firstFreeColumn = i;
                    if (freeColumns == 2)
                        secondFreeColumn = i;
                }
            }

            //Wenn nur mehr wenige Spalten frei sind (Ende des Spieles)
            if (freeColumns == 1 || (freeColumns == 2 && (secondFreeColumn - firstFreeColumn >= 4)))
            {
                if (acuteThreat(p, p.toMove) == -1 && acuteThreat(p, !p.toMove) == -1)
                {
                    value_Renamed = evaluate(p, true);
                    pv.length = 0;
                    addHashEntries(Zkey, index, depth + extension, value_Renamed, HASHEXACT, -1);
                    return value_Renamed;
                }
            }


            if (depth <= (0 - extension))
            {
                int akut2 = acuteThreat(p, p.toMove);
                if (akut2 != -1)
                {
                    pv.length = 0;
                    addHashEntries(Zkey, index, depth + extension, 1000 - p.numberOfDiscs() - 1, HASHEXACT, -1);
                    return 1000 - p.numberOfDiscs() - 1;
                }
                int akut = acuteThreat(p, !p.toMove);
                if (akut == -1)
                {
                    pv.length = 0;
                    int val = evaluate(p, false);
                    addHashEntries(Zkey, index, depth + extension, val, HASHEXACT, -1);
                    return val;
                }
                extension += 2;
                Zkey = Zkey ^ (p.toMove ? zobristKeys[akut][0] : zobristKeys[akut][1]);
                int value_Renamed = -AlphaBeta(p, depth - 1, -beta, -alpha, extension, mypv, Zkey, akut);
                p.undoMove(akut);
                Zkey = Zkey ^ (p.toMove ? zobristKeys[akut][0] : zobristKeys[akut][1]);
                if (value_Renamed >= beta)
                {
                    addHashEntries(Zkey, index, depth + extension - 2, beta, HASHBETA, -1);
                    return beta;
                }
                if (value_Renamed > alpha)
                {
                    hashflag = HASHEXACT;
                    alpha = value_Renamed;
                    pv.First = new MoveListElement(akut);
                    if (mypv.length != 0)
                    {
                        pv.Rest = mypv;
                    }
                    pv.length = mypv.length + 1;
                }
                addHashEntries(Zkey, index, depth + extension - 2, alpha, hashflag, -1);
                return alpha;
            }

            int[] moves = generateMoves(p, searchDepth - depth);
            sort(moves, p);  //Sortiert Züge nach Feldgewichten und nach dem besten Zug aus den Hash Tables

            //Suchvertiefung
            for (int i = 0; i < moves[7]; i++)
            {
                Zkey = Zkey ^ (p.toMove ? zobristKeys[moves[i]][0] : zobristKeys[moves[i]][1]);
                value_Renamed = -AlphaBeta(p, depth - 1, -beta, -alpha, extension, mypv, Zkey, moves[i]);
                p.undoMove(moves[i]);
                Zkey = Zkey ^ (p.toMove ? zobristKeys[moves[i]][0] : zobristKeys[moves[i]][1]);
                if (value_Renamed >= beta)
                {
                    addHashEntries(Zkey, index, depth + extension, value_Renamed, HASHBETA, moves[i]);
                    return beta;
                }
                if (value_Renamed > alpha)
                {
                    hashflag = HASHEXACT;
                    alpha = value_Renamed;
                    pv.First = new MoveListElement(moves[i]);
                    if (mypv.length != 0)
                    {
                        pv.Rest = mypv;
                    }
                    pv.length = mypv.length + 1;
                }
            }
            addHashEntries(Zkey, index, depth + extension, alpha, hashflag, (hashflag == HASHEXACT ? pv.pop() : -1));
            return alpha;
        }
예제 #2
0
        /*
        *	Für den initialen Aufruf von AlphaBeta gibt es eine spezielle Funktion.
        *	a) Hier wird kein Wert aus den Hash Tables, aus dem Eröffnungsbuch oder aus einer Form von Evaluation übernommen,
        *	da man sonst 0 Level im Suchbaum und demzufolge keine PV, also auch keinen besten Zug erhält.
        *	b) Hier muß nicht auf gewonnene oder unentschiedene Positionen getestet werden, da playGame() solche Stellungen abfängt.
        *	c) Hier wird kein Zug-Argument übergeben. Diese Methode stellt stets den Wurzelknoten dar.
        */

        public virtual int StartAlphaBeta(Position p, int depth, int alpha, int beta, double extension, MoveList pv, long Zkey)
        {                        
            nodecount[0] += 1;
            int hashflag = HASHALPHA;

            //letzte Bits des Keys in Index umwandeln
            int index = (int)Zkey & (HASHSIZE - 1);
           
            //Hashtables zugriff
            bestMove = -1;
            if (HashTable1[index].key == Zkey) //HashTable 1 suchen
            {
                bestMove = HashTable1[index].move;
            }
            if (HashTable2[index].key == Zkey) //in HashTable 2 suchen
            {
                bestMove = HashTable2[index].move;
            }
           
            MoveList mypv = new MoveList();

            int[] moves = generateMoves(p, searchDepth - depth);    //mögliche Züge generieren
            sort(moves, p);     //Sortiert Züge nach Feldgewichten und nach dem besten Zug aus den Hash Tables 
          
            for (int i = 0; i < moves[7]; i++)  //moves[7] = Anzahl der möglichen Züge
            {
                Zkey = Zkey ^ (p.toMove == Position.WHITE ? zobristKeys[moves[i]][0] : zobristKeys[moves[i]][1]);
                value_Renamed = -AlphaBeta(p, depth - 1, -beta, -alpha, extension, mypv, Zkey, moves[i]);
                p.undoMove(moves[i]);
                Zkey = Zkey ^ (p.toMove == Position.WHITE ? zobristKeys[moves[i]][0] : zobristKeys[moves[i]][1]);
                if (value_Renamed >= beta)
                {
                    addHashEntries(Zkey, index, depth + extension, value_Renamed, HASHBETA, moves[i]);
                    return beta;
                }
                if (value_Renamed > alpha)
                {
                    hashflag = HASHEXACT;
                    alpha = value_Renamed;
                    pv.First = new MoveListElement(moves[i]);
                    if (mypv.length != 0)
                    {
                        pv.Rest = mypv;
                    }
                    pv.length = mypv.length + 1;
                }
            }
            addHashEntries(Zkey, index, depth + extension, alpha, hashflag, (hashflag == HASHEXACT ? pv.pop() : -1));
            return alpha;
        }