Beispiel #1
0
    // alpha beta with iterative deepening
    private static string PerformNearMove(Path shortestPath)
    {
        int depth = 0;
        float time = 0;
        float score, bestScore;
        GameState gs = new GameState();
        Point p = new Point();
        // default to something that won't kill us - server sometimes
        // runs out of time WAY early resulting in no time to perform alpha beta
        // iterations
        string bestMove = Map.MOVES[0]; //PerformFoolishRandomMove();
        DateTime lastAlphaBeta;

        List<string> ties = new List<string>();

        string[] moves = new string[4];
        float[] scores = new float[4];	// 0 north, 1 south, 2 east, 3 west
        scores[0]=3;
        scores[1]=2;
        scores[2]=1;
        scores[3]=0;

        // used to adjust time estimate for next depth so we don't go over time limit
        float timebase = ((float)Map.Width() * (float)Map.Height()) / (15f * 15f);

        while(Duration() + time < (TIME_LIMIT - TIME_THRESHOLD) && depth <= 12) {
        score = int.MinValue;
        bestScore = int.MinValue;
        depth++;

        // order moves by previous iterations scores
        // TODO this really does nothing. Cache of game states is needed
        // for quick eval retrival and move ordering
        int length = scores.Length;
        bool swapped = true;

        moves[0] = "North";
        moves[1] = "South";
        moves[2] = "East";
        moves[3] = "West";

        while(swapped) {
            swapped = false;
            for(int b=0; b<length - 1; b++) {
                if (scores[b] < scores[b+1]) {
                    string tmp = moves[b];
                    float ftmp = scores[b];

                    moves[b] = moves[b+1];
                    scores[b] = scores[b+1];

                    moves[b+1] = tmp;
                    scores[b+1] = ftmp;

                    swapped = true;
                }
            }
            length -= 1;

            //Console.Error.WriteLine("best:" + best + " score:" + scores[best]);
        }

        for(int i=0; i<moves.Length; i++) {
            string move = moves[i];
            p.X = Map.MyX(); p.Y = Map.MyY();
            p.MoveInDirection(move);
            if (!Map.IsWall(p.X, p.Y)) {
                // negate since starting with opponents moves
                lastAlphaBeta = DateTime.Now;
                score = -AlphaBeta(gs.ApplyMoveToMeAndCreate(move), depth, -int.MaxValue, -(-int.MaxValue), false);

                // estimate time for next depth
                TimeSpan ts = DateTime.Now - lastAlphaBeta;
                time = (float)ts.Milliseconds * (depth * timebase);
            } else {
                score = int.MinValue;
            }
            //Console.Error.WriteLine("alphabeta:" + move + ":" + score + " depth:" + depth);
            if (score > bestScore) {
                bestMove = move;
                bestScore = score;
                ties.Clear();
                ties.Add(bestMove);
            } else if (score == bestScore) {
                ties.Add(move);
            }

            // track score
            string temp = move.Substring(0, 1).ToUpper();
            int firstChar = (int)temp[0];
            switch(firstChar) {
            case 'N':
                scores[0] = score;
                break;
            case 'S':
                scores[1] = score;
                break;
            case 'E':
                scores[2] = score;
                break;
            case 'W':
                scores[3] = score;
                break;
            }
        }
        depth++;
        }

        List<string> secondaryTies = new List<string>();
        // break ties
        if (ties.Count > 1) {
        bestScore = int.MinValue;
        foreach(string move in ties) {
            //Console.Error.WriteLine("alpha tie break:" + move);
            p.X = Map.MyX(); p.Y = Map.MyY();
            p.MoveInDirection(move);
            if (Map.IsWall(p.X, p.Y)) {
                continue;
            }

            Territory room = new Territory(gs.ApplyMoveToMeAndCreate(move));
            room.DetermineTerritories();
            score = (float)room.GetMySize() - (float)room.GetOpponentSize();

            //Console.Error.WriteLine("alpha tie break:" + move + ":" + score);
            if (score > bestScore) {
                bestScore = score;
                bestMove = move;
                secondaryTies.Clear();
                secondaryTies.Add(move);
            } else if (score == bestScore) {
                secondaryTies.Add(move);
            }
        }
        }

        // kinda lame, but need another tie breaker...quick and dirty
        if (secondaryTies.Count > 1) {
        bestScore = int.MinValue;
        foreach(string move in ties) {
            if (shortestPath != null) {
                if (move.Equals(shortestPath.direction)) {
                    bestMove = shortestPath.direction;
                    break;
                }
            }
            p.X = Map.MyX(); p.Y = Map.MyY();
            p.MoveInDirection(move);
            if (Map.IsWall(p.X, p.Y)) {
                continue;
            }
            score = -GetEuclideanOpponentDistance(p.X, p.Y);
            //Console.Error.WriteLine("alpha tie break:" + move + ":" + score);
            if (score > bestScore) {
                bestScore = score;
                bestMove = move;
            }
        }
        }

        return bestMove;
    }
Beispiel #2
0
    // Evaluation function for alpha-beta pruning / minimax
    private static float EvaluateMove(GameState gs)
    {
        if (gs.IsMyWin()) {
        return MAX_MAP_SIZE;
        }

        if (gs.IsOpponentWin()) {
        return -MAX_MAP_SIZE;
        }

        if (gs.IsDraw()) {
        //		return 0
        }

        Territory room = new Territory(gs);
        room.DetermineTerritories();

        int mySize = room.GetMySize();
        int opponentSize = room.GetOpponentSize();
        int size = room.GetMySize() - room.GetOpponentSize();
        //Console.Error.WriteLine(String.Format("my room:{0} other room:{1}",mySize,opponentSize));

        return (float)size;
    }