Esempio n. 1
0
 public void Setup(Map m, PathFinder pathing)
 {
     pFinder = pathing;
     map = m;
 }
Esempio n. 2
0
        public void computeAllPaths(Map map)
        {
            Point currentPoint = Point.Empty, previousPoint = Point.Empty, firstPoint = Point.Empty;
            MapSquare square, firstSquare, previousSquare, currentSquare;
            MapSquare square, firstSquare, previousSquare, currentSquare, perpSquare1, perpSquare2;
            double pathScore, calculatedSpeed;
            for (int i = 0; i < map.Width; i++)
            {
                //Starting a new row, reset the score
                pathScore = 1;
                calculatedSpeed = 1;
                for (int j = 0; j < map.Height; j++)
                {
                    firstPoint = new Point(i, j);
                    firstSquare = map.SquareOrDefault(firstPoint);
                    previousPoint = new Point(i, j - 1);
                    previousSquare = map.SquareOrDefault(previousPoint);
                    //Stop on lights, stop signs and after grass breaks
                    if (firstSquare == null || !firstSquare.IsDriveable || (previousSquare.IsDriveable && (!firstSquare.Signal || firstSquare.StopSigns == MapSquare.STOP_SIGNS.NONE)))
                    {
                        continue;
                    }
                    for (int k = j + 1; k < map.Height; k++)
                    {
                        perpSquare1 = map.SquareOrDefault(new Point(i + 1, k));
                        perpSquare2 = map.SquareOrDefault(new Point(Math.Max(0, i - 1), k));
                        previousPoint = new Point(i, k - 1);
                        previousSquare = map.SquareOrDefault(previousPoint);
                        currentPoint = new Point(i, k);
                        currentSquare = map.SquareOrDefault(currentPoint);
                        if (!currentSquare.IsDriveable)
                        {
                            //Reached the end of the path
                            paths.Add(new Path(firstPoint, previousPoint, pathScore / (previousPoint.Y - firstPoint.Y + previousPoint.X - firstPoint.X + 1)));
                            break;
                        }
                        calculatedSpeed = Math.Max(MIN_SPEED, Math.Min(calculatedSpeed + 0.1, MAX_SPEED));
                        pathScore += calculatedSpeed;
                        if (currentSquare.Signal || currentSquare.StopSigns != MapSquare.STOP_SIGNS.NONE || (perpSquare1 != null && perpSquare1.IsDriveable) || (perpSquare2 != null && perpSquare2.IsDriveable))
                        {
                            paths.Add(new Path(firstPoint, currentPoint, pathScore / (currentPoint.Y - firstPoint.Y + currentPoint.X - firstPoint.X)));
                            if (currentSquare.StopSigns == MapSquare.STOP_SIGNS.STOP_NORTH || currentSquare.StopSigns == MapSquare.STOP_SIGNS.STOP_SOUTH)
                            {
                                //Stop sign is the end of a continuous drivable segment
                                break;
                            }
                        }

                    }
                }
            }

            for (int i = 0; i < map.Height; i++)
            {
                //Starting a new row, reset the score
                pathScore = 1;
                calculatedSpeed = 1;
                for (int j = 0; j < map.Width; j++)
                {
                    firstPoint = new Point(j, i);
                    firstSquare = map.SquareOrDefault(firstPoint);
                    previousPoint = new Point(j - 1, i);
                    previousSquare = map.SquareOrDefault(previousPoint);
                    //Stop on lights, stop signs and after grass breaks
                    if (firstSquare == null || !firstSquare.IsDriveable || (previousSquare.IsDriveable && (!firstSquare.Signal || firstSquare.StopSigns == MapSquare.STOP_SIGNS.NONE)))
                    {
                        continue;
                    }
                    for (int k = j + 1; k < map.Width; k++)
                    {
                        perpSquare1 = map.SquareOrDefault(new Point(k, i + 1));
                        perpSquare2 = map.SquareOrDefault(new Point(k, Math.Max(0, i - 1)));
                        previousPoint = new Point(k - 1, i);
                        previousSquare = map.SquareOrDefault(previousPoint);
                        currentPoint = new Point(k, i);
                        currentSquare = map.SquareOrDefault(currentPoint);
                        if (!currentSquare.IsDriveable)
                        {
                            //Reached the end of the path
                            paths.Add(new Path(firstPoint, previousPoint, pathScore / (previousPoint.Y - firstPoint.Y + previousPoint.X - firstPoint.X + 1)));
                            break;
                        }
                        calculatedSpeed = Math.Max(MIN_SPEED, Math.Min(calculatedSpeed + 0.1, MAX_SPEED));
                        pathScore += calculatedSpeed;
                        if (currentSquare.Signal || currentSquare.StopSigns != MapSquare.STOP_SIGNS.NONE || (perpSquare1 != null && perpSquare1.IsDriveable) || (perpSquare2 != null && perpSquare2.IsDriveable))
                        {
                            paths.Add(new Path(firstPoint, currentPoint, pathScore / (currentPoint.Y - firstPoint.Y + currentPoint.X - firstPoint.X)));
                            if (currentSquare.StopSigns == MapSquare.STOP_SIGNS.STOP_EAST || currentSquare.StopSigns == MapSquare.STOP_SIGNS.STOP_WEST)
                            {
                                //Stop sign is the end of a continuous drivable segment
                                break;
                            }
                        }

                    }
                }
            }

            /* ORIGINAL IMPLEMENTATION

                    currentPoint = new Point(i, j);
                    square = map.SquareOrDefault(currentPoint);
                    //Not a road tile or not driveable or IS a stop sign or IS a light
                    //TODO: Fix light logic
                    if (square == null || !square.IsDriveable || (firstPoint != Point.Empty && (square.StopSigns != MapSquare.STOP_SIGNS.NONE || square.Signal)))
                    {
                        if (square.StopSigns != MapSquare.STOP_SIGNS.NONE || square.Signal)
                        {
                            //Hacky fix to intersection overlap
                            previousPoint = currentPoint;
                            MapSquare nextSquare = map.SquareOrDefault(new Point(i, j + 1));
                            if (nextSquare != null && nextSquare.IsDriveable)
                            {
                                j--;
                            }
                        }
                        //We have a path of at least length 1
                        //TODO: Fix when we have a point at 0,0
                        if (firstPoint != Point.Empty)
                        {
                            paths.Add(new Path(firstPoint, previousPoint, pathScore / (previousPoint.Y - firstPoint.Y)));
                        }
                        calculatedSpeed = 0;
                        pathScore = 0;
                        firstPoint = Point.Empty;
                        previousPoint = Point.Empty;
                        continue;
                    }
                    //We have a road tile!
                    //Starting a new segment
                    if (calculatedSpeed == 0)
                    {
                        if (map.SquareOrDefault(previousPoint).IsDriveable)
                        {
                            firstPoint = previousPoint;
                            calculatedSpeed = 1;
                            pathScore = 1;
                        }
                        else
                        {
                            firstPoint = currentPoint;
                        }
                    }
                    calculatedSpeed = Math.Max(MIN_SPEED, Math.Min(calculatedSpeed + 0.1, MAX_SPEED));
                    pathScore += calculatedSpeed;
                    previousPoint = currentPoint;
                }
            }

            for (int i = 0; i < map.Height; i++)
            {
                //Starting a new row, reset the score
                pathScore = 0;
                calculatedSpeed = 0;
                for (int j = 0; j < map.Width; j++)
                {
                    currentPoint = new Point(j, i);
                    square = map.SquareOrDefault(currentPoint);
                    //Not a road tile or not driveable or IS a stop sign or IS a light
                    //TODO: Fix light logic
                    if (square == null || !square.IsDriveable || (firstPoint != Point.Empty && (square.StopSigns != MapSquare.STOP_SIGNS.NONE || square.Signal)))
                    {
                        if (square.StopSigns != MapSquare.STOP_SIGNS.NONE || square.Signal)
                        {
                            //Hacky fix to intersection overlap
                            previousPoint = currentPoint;
                            MapSquare nextSquare = map.SquareOrDefault(new Point(j+1, i));
                            if (nextSquare != null && nextSquare.IsDriveable)
                            {
                                j--;
                            }
                        }
                        //We have a path of at least length 1
                        //TODO: Fix when we have a point at 0,0
                        if (firstPoint != Point.Empty)
                        {
                            paths.Add(new Path(firstPoint, previousPoint, pathScore / (previousPoint.X - firstPoint.X)));
                        }
                        calculatedSpeed = 0;
                        firstPoint = Point.Empty;
                        previousPoint = currentPoint;
                        continue;
                    }
                    //We have a road tile!
                    //Starting a new segment
                    if (calculatedSpeed == 0)
                    {
                        if (map.SquareOrDefault(previousPoint).IsDriveable)
                        {
                            firstPoint = previousPoint;
                            calculatedSpeed = 1;
                            pathScore = 1;
                        }
                        else
                        {
                            firstPoint = currentPoint;
                        }
                    }
                    calculatedSpeed = Math.Max(MIN_SPEED, Math.Min(calculatedSpeed + 0.1, MAX_SPEED));
                    pathScore += calculatedSpeed;
                    previousPoint = currentPoint;

                }
            }
             */
            //Clean up the paths to remove length 1 paths that are in other paths
            paths = (from a in paths orderby a.start.X, a.start.Y select a).ToList();
            IQueryable<Path> path1 = (from a in paths where (a.end.X == a.start.X && a.end.Y == a.start.Y) orderby a.start.X, a.end.X, a.start.Y, a.end.Y select a).AsQueryable();
            IQueryable<Path> pathOver1 = (from a in paths where (a.end.X - a.start.X) + (a.end.Y - a.start.Y) > 0 orderby a.start.X, a.end.X, a.start.Y, a.end.Y select a).AsQueryable();
            foreach (Path p in path1){

                foreach (Path p1 in pathOver1)
                {
                    if (p.start.X >= p1.start.X && p.start.X <= p1.end.X && p.start.Y >= p1.start.Y && p.start.Y <= p1.end.Y)
                    {
                        paths.Remove(p);
                    }
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Calculate a path from start to end. No comments about how this is the world's worst A* implementation. It is purposely 
        /// simplistic to leave the teams the opportunity to improve greatly upon this. (I was yelled at last year for making the 
        /// sample A.I.'s too good.)
        /// </summary>
        /// <param name="map">The game map.</param>
        /// <param name="start">The tile units of the start point (inclusive).</param>
        /// <param name="end">The tile units of the end point (inclusive).</param>
        /// <returns>The path from start to end.</returns>
        public static List<Point> CalculatePath(Map map, Point start, Point end)
        {
            // should never happen but just to be sure
            if (start == end)
                return new List<Point> { start };

            // nodes are points we have walked to
            Dictionary<Point, TrailPoint> nodes = new Dictionary<Point, TrailPoint>();
            // points we have in a TrailPoint, but not yet evaluated.
            List<TrailPoint> notEvaluated = new List<TrailPoint>();

            TrailPoint tpOn = new TrailPoint(start, end, 0);
            while (true)
            {
                nodes.Add(tpOn.MapTile, tpOn);

                // get the neighbors
                TrailPoint tpClosest = null;
                foreach (Point ptOffset in offsets)
                {
                    Point pt = new Point(tpOn.MapTile.X + ptOffset.X, tpOn.MapTile.Y + ptOffset.Y);
                    MapSquare square = map.SquareOrDefault(pt);
                    // off the map or not a road/bus stop
                    if ((square == null) || (!square.IsDriveable))
                        continue;

                    // already evaluated - add it in
                    if (nodes.ContainsKey(pt))
                    {
                        TrailPoint tpAlreadyEvaluated = nodes[pt];
                        tpAlreadyEvaluated.Cost = Math.Min(tpAlreadyEvaluated.Cost, tpOn.Cost + 1);
                        tpOn.Neighbors.Add(tpAlreadyEvaluated);
                        continue;
                    }

                    // add this one in
                    TrailPoint tpNeighbor = new TrailPoint(pt, end, tpOn.Cost + 1);
                    tpOn.Neighbors.Add(tpNeighbor);
                    // may already be in notEvaluated. If so remove it as this is a more recent cost estimate
                    int indTp = notEvaluated.FindIndex(tp => tp.MapTile == tpNeighbor.MapTile);
                    if (indTp != -1)
                        notEvaluated.RemoveAt(indTp);

                    // we only assign to tpClosest if it is closer to the destination. If it's further away, then we
                    // use notEvaluated below to find the one closest to the dest that we have not walked yet.
                    if (tpClosest == null)
                    {
                        if (tpNeighbor.Distance < tpOn.Distance)
                            // new neighbor is closer - work from this next.
                            tpClosest = tpNeighbor;
                        else
                            // this is further away - put in the list to try if a better route is not found
                            notEvaluated.Add(tpNeighbor);
                    }
                    else
                        if (tpClosest.Distance <= tpNeighbor.Distance)
                            // this is further away - put in the list to try if a better route is not found
                            notEvaluated.Add(tpNeighbor);
                        else
                        {
                            // this is closer than tpOn and another neighbor - use it next.
                            notEvaluated.Add(tpClosest);
                            tpClosest = tpNeighbor;
                        }
                }

                // re-calc based on neighbors
                tpOn.RecalculateDistance(ptOffMap, map.Width);

                // if no closest, then get from notEvaluated. This is where it guarantees that we are getting the shortest
                // route - we go in here if the above did not move a step closer. This may not either as the best choice
                // may be the neighbor we didn't go with above - but we drop into this to find the closest based on what we know.
                if (tpClosest == null)
                {
                    if (notEvaluated.Count == 0)
                    {
                        Trap.trap();
                        break;
                    }
                    // We need the closest one as that's how we find the shortest path.
                    tpClosest = notEvaluated[0];
                    int index = 0;
                    for (int ind = 1; ind < notEvaluated.Count; ind++)
                    {
                        TrailPoint tpNotEval = notEvaluated[ind];
                        if (tpNotEval.Distance >= tpClosest.Distance)
                            continue;
                        tpClosest = tpNotEval;
                        index = ind;
                    }
                    notEvaluated.RemoveAt(index);
                }

                // if we're at end - we're done!
                if (tpClosest.MapTile == end)
                {
                    tpClosest.Neighbors.Add(tpOn);
                    nodes.Add(tpClosest.MapTile, tpClosest);
                    break;
                }

                // try this one
                tpOn = tpClosest;
            }

            // Create the return path - from end back to beginning.
            List<Point> path = new List<Point>();
            tpOn = nodes[end];
            path.Add(tpOn.MapTile);
            while (tpOn.MapTile != start)
            {
                List<TrailPoint> neighbors = tpOn.Neighbors;
                int cost = tpOn.Cost;

                tpOn = tpOn.Neighbors[0];
                for (int ind = 1; ind < neighbors.Count; ind++)
                    if (neighbors[ind].Cost < tpOn.Cost)
                        tpOn = neighbors[ind];

                // we didn't get to the start.
                if (tpOn.Cost >= cost)
                {
                    Trap.trap();
                    return path;
                }
                path.Insert(0, tpOn.MapTile);
            }

            return path;
        }
Esempio n. 4
0
        public void IncomingMessage(string message)
        {
            try
            {
                DateTime startTime = DateTime.Now;
                // get the xml - we assume we always get a valid message from the server.
                XDocument xml = XDocument.Parse(message);

                switch (xml.Root.Name.LocalName)
                {
                    case "setup":
                        Console.Out.WriteLine("Received setup message");
                        if (log.IsInfoEnabled)
                            log.Info("Received setup message");

                        List<Player> players = Player.FromXml(xml.Root.Element("players"));
                        List<Company> companies = Company.FromXml(xml.Root.Element("companies"));
                        List<Passenger> passengers = Passenger.FromXml(xml.Root.Element("passengers"), companies);
                        Map map = new Map(xml.Root.Element("map"), companies);
                        myGuid = xml.Root.Attribute("my-guid").Value;
                        Player me2 = players.Find(plyr => plyr.Guid == myGuid);

                        brain.Setup(map, me2, players, companies, passengers, PlayerOrdersEvent);
                        break;

                    case "status":
                        // may be here because re-started and got this message before the re-send of setup.
                        if (string.IsNullOrEmpty(myGuid))
                        {
                            Trap.trap();
                            return;
                        }

                        PlayerAIBase.STATUS status = (PlayerAIBase.STATUS)Enum.Parse(typeof(PlayerAIBase.STATUS), xml.Root.Attribute("status").Value);
                        XAttribute attr = xml.Root.Attribute("player-guid");
                        string guid = attr != null ? attr.Value : myGuid;

                        lock (this)
                        {
                            if (signal > 0)
                            {
                                // bad news - we're throwing this message away.
                                Trap.trap();
                                return;
                            }
                            signal++;
                        }

                        Player.UpdateFromXml(brain.Players, brain.Passengers, xml.Root.Element("players"));
                        Passenger.UpdateFromXml(brain.Passengers, brain.Companies, xml.Root.Element("passengers"));

                        // update my path & pick-up.
                        Player plyrStatus = brain.Players.Find(plyr => plyr.Guid == guid);
                        XElement elem = xml.Root.Element("path");
                        if (elem != null)
                        {
                            string [] path = elem.Value.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries);
                            plyrStatus.Limo.Path.Clear();
                            foreach (string stepOn in path)
                            {
                                int pos = stepOn.IndexOf(',');
                                plyrStatus.Limo.Path.Add(new Point(Convert.ToInt32(stepOn.Substring(0, pos)), Convert.ToInt32(stepOn.Substring(0, pos))));
                            }
                        }

                        elem = xml.Root.Element("pick-up");
                        if (elem != null)
                        {
                            string [] names = elem.Value.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries);
                            plyrStatus.PickUp.Clear();
                            foreach (Passenger psngrOn in names.Select(pickupOn => brain.Passengers.Find(ps => ps.Name == pickupOn)))
                                plyrStatus.PickUp.Add(psngrOn);
                        }

                        // pass in to generate new orders
                        brain.GameStatus(status, plyrStatus, brain.Players, brain.Passengers);

                        lock (this)
                        {
                            signal--;
                        }
                        break;

                    case "exit":
                        Console.Out.WriteLine("Received exit message");
                        if (log.IsInfoEnabled)
                            log.Info("Received exit message");
                        Environment.Exit(0);
                        break;

                    default:
                        Trap.trap();
                        string msg = string.Format("ERROR: bad message (XML) from server - root node {0}", xml.Root.Name.LocalName);
                        log.Warn(msg);
                        Trace.WriteLine(msg);
                        break;
                }

                TimeSpan turnTime = DateTime.Now.Subtract(startTime);
                if (turnTime.TotalMilliseconds > 800)
                    Console.Out.WriteLine("WARNING - turn took {0} seconds", turnTime.TotalMilliseconds/1000);
            }
            catch (Exception ex)
            {
                Console.Out.WriteLine(string.Format("Error on incoming message. Exception: {0}", ex));
                log.Error("Error on incoming message.", ex);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Called at the start of the game.
        /// </summary>
        /// <param name="map">The game map.</param>
        /// <param name="me">You. This is also in the players list.</param>
        /// <param name="players">All players (including you).</param>
        /// <param name="companies">The companies on the map.</param>
        /// <param name="passengers">The passengers that need a lift.</param>
        /// <param name="ordersEvent">Method to call to send orders to the server.</param>
        public void Setup(Map map, Player me, List<Player> players, List<Company> companies, List<Passenger> passengers,
            PlayerAIBase.PlayerOrdersEvent ordersEvent)
        {
            try
            {
                pFinder = new PathFinder();
                GameMap = map;
                GameInfo = new GameStatusInfo();
                GameInfo.Setup(map, pFinder);
                Players = players;
                Me = me;
                Companies = companies;
                Passengers = passengers;
                sendOrders = ordersEvent;

                List<Passenger> pickup = AllPickups(me, passengers);
                pFinder.computeAllPaths(map);
                pFinder.generateAdjacencyMatrix();

                // get the path from where we are to the dest.
                List<Point> path = CalculatePathPlus1(me, pickup[0].Lobby.BusStop);
                sendOrders("ready", path, pickup);
            }
            catch (Exception ex)
            {
                log.Fatal(string.Format("Setup({0}, ...", me == null ? "{null}" : me.Name), ex);
            }
        }