示例#1
0
        /// <summary>
        /// Call the AI with a status message.
        /// </summary>
        /// <param name="xmlMessage">Can be null. The remote AI XML for a message without the status or my player values set.</param>
        /// <param name="about">The player this status is about. Will be set to receiving user for status not specific to a player.</param>
        /// <param name="status">The status for this message.</param>
        /// <param name="players">All the players.</param>
        /// <param name="passengers">All the passengers.</param>
        public void GameStatus(XDocument xmlMessage, Player about, PlayerAIBase.STATUS status, List<Player> players, List<Passenger> passengers)
        {
            // only care if for me, and an action (ie not status)
            if ((status == PlayerAIBase.STATUS.UPDATE) || ((about != null) && (about.Guid != aiWorker.MyPlayerGuid)))
                return;

            Player player = players.Find(pl => pl.Guid == aiWorker.MyPlayerGuid);
            Trap.trap(about == null);
            if (about == null)
                about = player;
            aiWorker.AddMessage(status, about, AllPickups(player, passengers));
        }
示例#2
0
 private void toolStripMenuItemSetDest_Click(object sender, EventArgs e)
 {
     playerMouseSetDest = contextMenuRMB.Tag as Player;
     Cursor = Cursors.Cross;
 }
示例#3
0
        private void mapDisplay_MouseClickedEvent(Point mapUnits, MouseButtons buttons)
        {
            Cursor = Cursors.Default;
            if (GameFramework.Mode != Framework.COMM_STATE.PAUSED && GameFramework.Mode != Framework.COMM_STATE.READY_TO_START)
            {
                playerMouseMove = playerMouseSetDest = null;
                return;
            }

            if ((buttons & MouseButtons.Right) != 0)
            {
                foreach (Player plyrOn in GameFramework.GameEngine.Players)
                {
                    int xDiff = Math.Abs(plyrOn.Limo.Location.MapPosition.X - mapUnits.X);
                    int yDiff = Math.Abs(plyrOn.Limo.Location.MapPosition.Y - mapUnits.Y);
                    if ((xDiff >= PixelsPerTile/4) || (yDiff >= PixelsPerTile/4))
                        continue;
                    contextMenuRMB.Tag = plyrOn;
                    foreach (ToolStripMenuItem menu in toolStripMenuItemSetPassenger.DropDownItems)
                        menu.Enabled = !plyrOn.PassengersDelivered.Contains((Passenger) menu.Tag);
                    contextMenuRMB.Show(MousePosition);
                    return;
                }
                Console.Beep();
                return;
            }

            if (((buttons & MouseButtons.Left) == 0) || (playerMouseMove == null && playerMouseSetDest == null))
                return;

            // get the quarter tile location (needed for direction) on car move.
            Point ptQuarter = new Point(mapUnits.X/(TileMovement.UNITS_PER_TILE/2), mapUnits.Y/(TileMovement.UNITS_PER_TILE/2));
            Point ptTile = new Point(ptQuarter.X/2, ptQuarter.Y/2);

            // can only set the car or dest in a road or bus-stop
            MapSquare square = GameFramework.GameEngine.MainMap.SquareOrDefault(ptTile);
            if (square == null)
            {
                Console.Beep();
                Trap.trap();
                return;
            }

            if (playerMouseSetDest != null)
            {
                if (square.Tile.Type != MapTile.TYPE.BUS_STOP)
                {
                    Console.Beep();
                    playerMouseMove = playerMouseSetDest = null;
                    return;
                }

                List<Point> path = SimpleAStar.CalculatePath(GameFramework.GameEngine.MainMap,
                                                             playerMouseSetDest.Limo.Location.TilePosition, ptTile);
                if (path.Count > 1)
                    path.Add(path[path.Count - 2]);
                GameFramework.GameEngine.ProcessAllMoveMessages();
                GameFramework.GameEngine.PlayerOrders(playerMouseSetDest, path, new List<Passenger>());
                playerMouseMove = playerMouseSetDest = null;
            }

            if (playerMouseMove != null)
            {
                if (square.Tile.Type != MapTile.TYPE.ROAD && square.Tile.Type != MapTile.TYPE.BUS_STOP)
                {
                    Console.Beep();
                    playerMouseMove = playerMouseSetDest = null;
                    return;
                }

                // process before we change the location.
                GameFramework.GameEngine.ProcessAllMoveMessages();

                switch (square.Tile.Direction)
                {
                    case MapTile.DIRECTION.NORTH_SOUTH:
                        playerMouseMove.Limo.SetTileLocation(square, ptTile,
                                                             (ptQuarter.X & 1) == 1
                                                             	? MapSquare.COMPASS_DIRECTION.NORTH
                                                             	: MapSquare.COMPASS_DIRECTION.SOUTH);
                        break;
                    case MapTile.DIRECTION.EAST_WEST:
                        playerMouseMove.Limo.SetTileLocation(square, ptTile,
                                                             (ptQuarter.Y & 1) == 1
                                                             	? MapSquare.COMPASS_DIRECTION.EAST
                                                             	: MapSquare.COMPASS_DIRECTION.WEST);
                        break;

                    case MapTile.DIRECTION.INTERSECTION:
                        if ((ptQuarter.X & 1) == 1 && (ptQuarter.Y & 1) == 1)
                            playerMouseMove.Limo.SetTileLocation(square, ptTile, MapSquare.COMPASS_DIRECTION.NORTH);
                        else if ((ptQuarter.X & 1) == 0 && (ptQuarter.Y & 1) == 1)
                            playerMouseMove.Limo.SetTileLocation(square, ptTile, MapSquare.COMPASS_DIRECTION.EAST);
                        else if ((ptQuarter.X & 1) == 0 && (ptQuarter.Y & 1) == 0)
                            playerMouseMove.Limo.SetTileLocation(square, ptTile, MapSquare.COMPASS_DIRECTION.SOUTH);
                        else
                            playerMouseMove.Limo.SetTileLocation(square, ptTile, MapSquare.COMPASS_DIRECTION.WEST);
                        break;

                    default:
                        Console.Beep();
                        playerMouseMove = playerMouseSetDest = null;
                        return;
                }

                Point ptDest = playerMouseMove.NextBusStop != null
                               	? playerMouseMove.NextBusStop.BusStop
                               	: (playerMouseMove.Limo.PathTiles.Count > 1
                               	   	? playerMouseMove.Limo.PathTiles[playerMouseMove.Limo.PathTiles.Count - 2]
                               	   	: Point.Empty);
                List<Point> path;
                if (ptDest != Point.Empty)
                {
                    path = SimpleAStar.CalculatePath(GameFramework.GameEngine.MainMap, playerMouseMove.Limo.Location.TilePosition,
                                                     ptDest);
                    if (path.Count > 1)
                        path.Add(path[path.Count - 2]);
                }
                else
                    path = new List<Point>();
                GameFramework.GameEngine.PlayerOrders(playerMouseMove, path, new List<Passenger>());

                playerMouseMove = playerMouseSetDest = null;
                mapDisplay.Invalidate();
                UpdatePlayers();
                UpdateDebug();
            }
        }
示例#4
0
        /// <summary>
        /// Called when the game starts, providing all info.
        /// </summary>
        public void Setup(GameMap map, Player me, List<Player> players, List<Company> companies, List<Passenger> passengers, PlayerAIBase.PlayerOrdersEvent ordersEvent)
        {
            sendOrders = ordersEvent;

            XDocument doc = new XDocument();
            XElement elemRoot = new XElement("setup", new XAttribute("game-start", true), new XAttribute("my-guid", me.Guid));
            doc.Add(elemRoot);

            // the map
            XElement elemMap = new XElement("map", new XAttribute("width", map.Width), new XAttribute("height", map.Height), new XAttribute("units-tile", TileMovement.UNITS_PER_TILE));
            elemRoot.Add(elemMap);
            for (int x = 0; x < map.Width; x++ )
                for (int y = 0; y < map.Height; y++)
                {
                    MapSquare square = map.Squares[x][y];
                    XElement elemRow = new XElement("tile", new XAttribute("x", x), new XAttribute("y", y),
                                                    new XAttribute("type", square.Tile.Type));
                    if (square.Tile.IsDriveable)
                    {
                        elemRow.Add(new XAttribute("direction", square.Tile.Direction));
                        if (square.StopSigns != MapSquare.STOP_SIGNS.NONE)
                            elemRow.Add(new XAttribute("stop-sign", square.StopSigns));
                        if (square.SignalDirection != MapSquare.SIGNAL_DIRECTION.NONE)
                            elemRow.Add(new XAttribute("signal", true));
                    }
                    elemMap.Add(elemRow);
                }

            // all players (including me)
            XElement elemPlayers = new XElement("players");
            elemRoot.Add(elemPlayers);
            foreach (Player plyrOn in players)
                elemPlayers.Add(new XElement("player", new XAttribute("guid", plyrOn.Guid),
                                                   new XAttribute("name", plyrOn.Name),
                                                   new XAttribute("limo-x", plyrOn.Limo.Location.TilePosition.X),
                                                   new XAttribute("limo-y", plyrOn.Limo.Location.TilePosition.Y),
                                                   new XAttribute("limo-angle", plyrOn.Limo.Location.Angle)));

            // all companies
            XElement elemCompanies = new XElement("companies");
            elemRoot.Add(elemCompanies);
            foreach (Company cmpnyOn in companies)
                elemCompanies.Add(new XElement("company", new XAttribute("name", cmpnyOn.Name),
                            new XAttribute("bus-stop-x", cmpnyOn.BusStop.X), new XAttribute("bus-stop-y", cmpnyOn.BusStop.Y)));

            // all passengers
            XElement elemPassengers = new XElement("passengers");
            elemRoot.Add(elemPassengers);
            foreach (Passenger psngrOn in passengers)
            {
                XElement elemPassenger = new XElement("passenger", new XAttribute("name", psngrOn.Name), new XAttribute("points-delivered", psngrOn.PointsDelivered));
                // if due to a re-start, these can be null
                if (psngrOn.Lobby != null)
                    elemPassenger.Add(new XAttribute("lobby", psngrOn.Lobby.Name));
                if (psngrOn.Destination != null)
                    elemPassenger.Add(new XAttribute("destination", psngrOn.Destination.Name));
                foreach (Company route in psngrOn.Companies)
                    elemPassenger.Add(new XElement("route", route.Name));
                foreach (Passenger enemy in psngrOn.Enemies)
                    elemPassenger.Add(new XElement("enemy", enemy.Name));
                elemPassengers.Add(elemPassenger);
            }

            framework.tcpServer.SendMessage(TcpGuid, doc.ToString());
        }
示例#5
0
 public StatusMessage(PlayerAIBase.STATUS status, Player player, List<Passenger> pickup)
 {
     Status = status;
     LimoTileLocation = player.Limo.Location.TilePosition;
     PassengerDestBusStop = player.Passenger == null ? Point.Empty : player.Passenger.Destination.BusStop;
     Pickup = pickup;
 }
示例#6
0
 /// <summary>
 /// List of all passengers we can pick up. Does not include ones already delivered and if presently carrying one,
 /// does not include that one. Returned in random order, different random order each time called.
 /// </summary>
 private static List<Passenger> AllPickups(Player me, IEnumerable<Passenger> passengers)
 {
     List<Passenger> pickup = new List<Passenger>();
     pickup.AddRange(passengers.Where(
             psngr =>
             (!me.PassengersDelivered.Contains(psngr)) && (psngr != me.Passenger) && (psngr.Car == null) &&
             (psngr.Destination != null)).OrderBy(psngr => rand.Next()));
     return pickup;
 }
示例#7
0
        private void ReadMessage(Player player, XElement root, out List<Point> path, out List<Passenger> pickup)
        {
            // get the requested path. Does not check that it is on the map or continuous - the engine checks that.
            path = new List<Point>();
            XElement element = root.Element("path");
            if (element != null)
            {
                string trail = element.Value;
                if (!string.IsNullOrEmpty(trail))
                {
                    string[] steps = trail.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string stepOn in steps)
                    {
                        string[] coords = stepOn.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                        int x, y;
                        if ((coords.Length != 2) || (!int.TryParse(coords[0], out x)) || (!int.TryParse(coords[1], out y)))
                        {
                            Trap.trap();
                            StatusMessage(string.Format("Player {0} provided an invalid path element {1}", player.Name, stepOn));
                            break;
                        }
                        path.Add(new Point(x, y));
                    }
                }
            }

            // get the requested pick-up list. Does not check for already delivered - the engine checks that.
            pickup = new List<Passenger>();
            element = root.Element("pick-up");
            if (element != null)
            {
                string allNames = element.Value;
                if (!string.IsNullOrEmpty(allNames))
                {
                    string[] names = allNames.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string nameOn in names)
                    {
                        Passenger psngr = GameEngine.Passengers.FirstOrDefault(ps => ps.Name == nameOn);
                        if (psngr != null)
                            pickup.Add(psngr);
                        else
                        {
                            Trap.trap();
                            StatusMessage(string.Format("Player {0} provided an invalid pick-up name {1}", player.Name, nameOn));
                        }
                    }
                }
            }
        }
示例#8
0
 /// <summary>
 /// Player is ready to start.
 /// </summary>
 /// <param name="player">The player. null if a join, non-null (maybe) if a re-join.</param>
 /// <param name="root">The XML message.</param>
 private void MsgPlayerOrders(Player player, XElement root)
 {
     List<Point> path;
     List<Passenger> pickup;
     ReadMessage(player, root, out path, out pickup);
     GameEngine.RemoteMessages.Enqueue(new Engine.AiMessage(player, path, pickup));
 }
示例#9
0
        internal void PlayerOrders(Player player, List<Point> path, List<Passenger> pickUp)
        {
            // sync up - try to find a node in the existing path that matches
            if (path.Count > 0)
            {
                // 1. new path has a match somewhere with the tile presently on (ie we've moved beyond the start of
                // a path that is duplicated for a bit, then goes elsewhere).
                for (int index = 0; index < path.Count; index++)
                    if (path[index] == player.Limo.Location.TilePosition)
                    {
                        if (index == 0)
                            break;
                        path.RemoveRange(0, index);
                        break;
                    }

                // 2. starts on the tile we're on (and this includes 1. above).
                if (player.Limo.Location.TilePosition == path[0])
                {
                    player.Limo.PathTiles.Clear();
                    // if we need a U-turn, we add the next tile and then the tile on again.
                    Point ptNext = player.Limo.Location.NextTilePosition;
                    if ((path.Count == 1) || (ptNext != path[1]))
                    {
                        // on this tile, then go into the next tile, then path[0] is back to this tile.
                        Trap.trap(!MainMap.SquareOrDefault(ptNext).Tile.IsDriveable);
                        player.Limo.PathTiles.Add(ptNext);
                    }

                    // set it to the new path
                    player.Limo.PathTiles.AddRange(path);
                }

                else
                {
                    // look for existing path has a match with the start of the new path (ie the new path is for
                    // when this path has gotten a little further).
                    bool foundMatch = false;
                    for (int index = 0; index < player.Limo.PathTiles.Count; index++)
                        if (player.Limo.PathTiles[index] == path[0])
                        {
                            player.Limo.PathTiles.RemoveRange(index, player.Limo.PathTiles.Count - index);
                            player.Limo.PathTiles.AddRange(path);
                            foundMatch = true;
                            break;
                        }

                    // no match - no new path and let the user know
                    if (!foundMatch)
                        player.GameStatus(null, player, PlayerAIBase.STATUS.NO_PATH, Players, Passengers);
                }

                for (int ind = 1; ind < player.Limo.PathTiles.Count; ind++)
                {
                    Company cmpy = companies.FirstOrDefault(cpy => cpy.BusStop == player.Limo.PathTiles[ind]);
                    if (cmpy != null)
                    {
                        player.NextBusStop = cmpy;
                        break;
                    }
                }
            }

            if (pickUp.Count <= 0)
                return;
            // new pick-up list.
            player.PickUp.Clear();
            foreach (Passenger psngrOn in pickUp.Where(psngrOn => (!player.PassengersDelivered.Contains(psngrOn))))
                player.PickUp.Add(psngrOn);
        }
示例#10
0
 public void RestartPlayer(Player player)
 {
     Trap.trap();
     player.Setup(MainMap, player, Players, companies, Passengers, PlayerAddOrder);
 }
示例#11
0
 private void ValidateData(Player plyr)
 {
 }
示例#12
0
        private void ValidateData(Player plyr)
        {
            // passengers ok?
            bool error = false;
            if (plyr.PassengersDelivered.Contains(plyr.Passenger))
            {
                if (log.IsWarnEnabled)
                    log.Warn(string.Format("Player {0} is carrying passenger {1} who was already delivered before", plyr.Name, plyr.Passenger.Name));
                error = true;
            }
            foreach (Passenger pickupOn in plyr.PickUp.Where(pickupOn => plyr.PassengersDelivered.Contains(pickupOn)))
            {
                if (log.IsWarnEnabled)
                    log.Warn(string.Format("Player {0} wants to pick up passenger {1} who was already delivered before", plyr.Name, pickupOn.Name));
                error = true;
            }

            // passenger location ok?
            foreach (Passenger psngrOn in Passengers)
            {
                if (psngrOn.Car != null && psngrOn.Lobby != null)
                {
                    if (log.IsWarnEnabled)
                        log.Warn(string.Format("Passenger {0} in car {1} and lobby {2}", psngrOn.Name, psngrOn.Car.Location.TilePosition, psngrOn.Lobby.Name));
                    error = true;
                }
                if (psngrOn.Lobby != null && ! psngrOn.Lobby.Passengers.Contains(psngrOn))
                {
                    if (log.IsWarnEnabled)
                        log.Warn(string.Format("Passenger {0} in lobby {1} but that company does not list it", psngrOn.Name, psngrOn.Lobby.Name));
                    error = true;
                }
            }
            foreach (Company cmpyOn in companies)
                foreach (Passenger psngrOn in cmpyOn.Passengers)
                    if (psngrOn.Lobby != cmpyOn)
                    {
                        if (log.IsWarnEnabled)
                            log.Warn(string.Format("Passenger {0} in lobby {1} but company {2} lists it", psngrOn.Name, psngrOn.Lobby == null ? "null" : psngrOn.Lobby.Name, cmpyOn.Name));
                        error = true;
                    }

            // path ok?
            foreach (Point ptTileOn in plyr.Limo.PathTiles)
            {
                MapTile tile = MainMap.Squares[ptTileOn.X][ptTileOn.Y].Tile;
                if (! tile.IsDriveable)
                {
                    if (log.IsWarnEnabled)
                        log.Warn(string.Format("Player {0} has path entry[{1}] which is of type {2}", plyr.Name, ptTileOn, tile.Type));
                    error = true;
                }
            }
            for (int ind = 1; ind < plyr.Limo.PathTiles.Count; ind++)
            {
                int x = Math.Abs(plyr.Limo.PathTiles[ind].X - plyr.Limo.PathTiles[ind - 1].X);
                int y = Math.Abs(plyr.Limo.PathTiles[ind].Y - plyr.Limo.PathTiles[ind - 1].Y);
                if (x + y != 1)
                {
                    if (log.IsWarnEnabled)
                        log.Warn(string.Format("Player {0} at path[{1}] illegal {2} -> {3}", plyr.Name, ind, plyr.Limo.PathTiles[ind-1], plyr.Limo.PathTiles[ind]));
                    error = true;
                }
            }

            #if STRICT
            // cars on top of each other (never should have 2 in the same quarter tile
            Point ptQtr = BoardLocation.MapToQuarterTile(plyr.Limo.Location.MapPosition);
            foreach (Player plyrOn in Players.Where(plyrOn => plyrOn != plyr).Where(plyrOn => ptQtr == BoardLocation.MapToQuarterTile(plyrOn.Limo.Location.MapPosition)))
            {
                if (log.IsWarnEnabled)
                    log.Warn(string.Format("Player {0} and Player {1} are both on quarter tile {2}", plyr.Name, plyrOn.Name, ptQtr));
                error = true;
            }
            #endif

            // car location ok?
            Point pt = plyr.Limo.Location.TilePosition;
            if (! MainMap.Squares[pt.X][pt.Y].Tile.IsDriveable)
            {
                if (log.IsWarnEnabled)
                    log.Warn(string.Format("Player {0} is located at {1} which is of type {2}", plyr.Name, plyr.Limo.Location, MainMap.Squares[pt.X][pt.Y].Tile.Type));
                error = true;
            }
            if (plyr.Limo.Location.OffsetTileMoves == 0)
            {
                int xOff = plyr.Limo.Location.MapPosition.X%TileMovement.UNITS_PER_TILE;
                int yOff = plyr.Limo.Location.MapPosition.Y%TileMovement.UNITS_PER_TILE;
                switch (plyr.Limo.Location.Direction)
                {
                    case MapSquare.COMPASS_DIRECTION.NORTH:
                        if (xOff != 18 || yOff != 0)
                        {
                            if (log.IsWarnEnabled)
                                log.Warn(string.Format("Player {0} is located at {1} which has a bad offset of {2},{3} (should be 18,0)", plyr.Name, plyr.Limo.Location, xOff, yOff));
                            error = true;
                        }
                        break;
                    case MapSquare.COMPASS_DIRECTION.EAST:
                        if (xOff != 0 || yOff != 18)
                        {
                            if (log.IsWarnEnabled)
                                log.Warn(string.Format("Player {0} is located at {1} which has a bad offset of {2},{3} (should be 18,0)", plyr.Name, plyr.Limo.Location, xOff, yOff));
                            error = true;
                        }
                        break;
                    case MapSquare.COMPASS_DIRECTION.SOUTH:
                        if (xOff != 6 || yOff != 0)
                        {
                            if (log.IsWarnEnabled)
                                log.Warn(string.Format("Player {0} is located at {1} which has a bad offset of {2},{3} (should be 18,0)", plyr.Name, plyr.Limo.Location, xOff, yOff));
                            error = true;
                        }
                        break;
                    case MapSquare.COMPASS_DIRECTION.WEST:
                        if (xOff != 0 || yOff != 6)
                        {
                            if (log.IsWarnEnabled)
                                log.Warn(string.Format("Player {0} is located at {1} which has a bad offset of {2},{3} (should be 18,0)", plyr.Name, plyr.Limo.Location, xOff, yOff));
                            error = true;
                        }
                        break;
                }
            }

            Trap.trap(error);
        }
示例#13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:System.Object"/> class.
 /// </summary>
 public AiMessage(Player player, List<Point> path, List<Passenger> pickup)
 {
     Player = player;
     Path = path;
     Pickup = pickup;
 }
示例#14
0
        public void Setup(GameMap map, Player me, List<Player> players, List<Company> companies, List<Passenger> passengers,
				   PlayerAIBase.PlayerOrdersEvent ordersEvent)
        {
            ai.Setup(map, me, players, companies, passengers, ordersEvent);
        }
示例#15
0
 /// <summary>
 /// Call the AI with a status message.
 /// </summary>
 /// <param name="xmlMessage">Can be null. The remote AI XML for a message without the status or my player values set.</param>
 /// <param name="about">The player this is about.</param>
 /// <param name="status">The status for this message.</param>
 /// <param name="players">All the players.</param>
 /// <param name="passengers">All the passengers.</param>
 public void GameStatus(XDocument xmlMessage, Player about, PlayerAIBase.STATUS status, List<Player> players, List<Passenger> passengers)
 {
     ai.GameStatus(xmlMessage, about, status, players, passengers);
 }
示例#16
0
 /// <summary>
 /// Create the window.
 /// </summary>
 /// <param name="player">The player this window is for.</param>
 public PlayerStatus(Player player)
 {
     InitializeComponent();
     Player = player;
 }
示例#17
0
        /// <summary>
        /// Player is (re)joining the game.
        /// </summary>
        /// <param name="player">The player. null if a join, non-null (maybe) if a re-join.</param>
        /// <param name="guid">The tcp guid of the message.</param>
        /// <param name="root">The XML message.</param>
        private void MsgPlayerJoining(Player player, string guid, XElement root)
        {
            // if the player exists do nothing because we're already set up (client sent it twice).
            if (player != null)
            {
                Trap.trap();
                log.Error(string.Format("Join on existing connected player. connection: {0}", guid));
                return;
            }

            // must have a name
            string name = AttributeOrNull(root, "name");
            if (string.IsNullOrEmpty(name))
            {
                Trap.trap();
                log.Error(string.Format("Join with no name refused. Guid: {0}", guid));
                tcpServer.CloseConnection(guid);
                return;
            }

            // if auto-run, must match
            if (AutoRunNumGames > 0)
            {
                if (! AutoRunUsers.Contains(name))
                {
                    log.Error(string.Format("Join from non auto-run player {0} refused. Guid: {1}", name, guid));
                    tcpServer.CloseConnection(guid);
                    return;
                }
            }

            // check for new connection on existing player
            player = engine.Players.FirstOrDefault(pl => pl.Name == name);
            if (player != null && player.TcpGuid == null)
            {
                player.TcpGuid = guid;
                // resend the setup (they may have re-started)
                if (commState != COMM_STATE.ACCEPTING_JOINS && commState != COMM_STATE.GAME_OVER)
                {
                    Trap.trap();
                    player.WaitingForReply = Player.COMM_MODE.WAITING_FOR_START;
                    GameEngine.RestartPlayer(player);
                }
                if (log.IsInfoEnabled)
                    log.Info(string.Format("Player {0} reconnected", name));
                mainWindow.StatusMessage(string.Format("Player {0} reconnected", name));
                return;
            }

            // unique name?
            player = engine.Players.FirstOrDefault(pl => pl.Name == name);
            if (player != null)
            {
                log.Error(string.Format("Player {0} name already exists, duplicate refused.", name));
                mainWindow.StatusMessage(string.Format("Player {0} name already exists, duplicate refused.", name));
                tcpServer.CloseConnection(guid);
                return;
            }

            int ind = engine.Players.Count;
            // do we have room?
            if (ind >= NUM_PLAYERS)
            {
                log.Error(string.Format("Can't add a {0}th player. Name: {1}", NUM_PLAYERS + 1, name));
                tcpServer.CloseConnection(guid);
                return;
            }

            // we're in progress - no new players
            if (commState != COMM_STATE.ACCEPTING_JOINS)
            {
                Trap.trap();
                log.Error(string.Format("Game in progress - new players not allowed. Name: {0}", name));
                mainWindow.StatusMessage(string.Format("game in progress - new players not allowed. Name: {0}", name));
                tcpServer.CloseConnection(guid);
                return;
            }

            // ok, we're all good. Create the player
            XElement elemAvatar = root.Element("avatar");
            Image avatar = null;
            if (elemAvatar != null)
            {
                try
                {
                    byte[] data = Convert.FromBase64String(elemAvatar.Value);
                    avatar = new Bitmap(new MemoryStream(data));
                    // bugbug - scale if not 32x32
                    if ((avatar.Width != 32) || (avatar.Height != 32))
                        mainWindow.StatusMessage(string.Format("Avatar for player {0} not 32x32", name));
                }
                catch (Exception ex)
                {
                    mainWindow.StatusMessage(string.Format("Avatar for player {0} had error {1}", name, ex.Message));
                }
            }

            string school = AttributeOrNull(root, "school");
            string language = AttributeOrNull(root, "language");
            player = new Player(Guid.NewGuid().ToString(), name, school, language, avatar, new Limo(engine.StartLocations[ind], robotBitmaps[ind]), playerColors[ind], new RemoteAI(this, guid));
            engine.Players.Add(player);

            // if we have 10, we're ready to go
            int maxPlayers = AutoRunNumGames == 0 ? NUM_PLAYERS : AutoRunUsers.Count;
            if (DebugStartMode || engine.Players.Count >= maxPlayers || (!string.IsNullOrEmpty(TestUser)))
                CloseJoins();

            string msg = string.Format("Player {0} joined from {1}", name, tcpServer.GetIpAddress(guid));
            log.Info(msg);
            mainWindow.StatusMessage(msg);

            mainWindow.NewPlayerAdded();
            mainWindow.UpdateMenu();
        }
示例#18
0
        private void BusStopOffOn(Player plyr, Point busStop)
        {
            Company cmpny = companies.FirstOrDefault(cpy => cpy.BusStop == busStop);
            if (cmpny == null)
            {
                if (log.IsInfoEnabled)
                    log.Info(string.Format("Player {0} enters bus stop {1} which is NOT a company", plyr.Name, busStop));
                return;
            }

            if (log.IsInfoEnabled)
            {
                log.Info(string.Format("Player {0} enters bus stop {1} with {2}", plyr.Name, cmpny.Name, plyr.Passenger == null ? "{none}" : plyr.Passenger.Name));
                if (cmpny.Passengers.Count > 0)
                    log.Info(string.Format("       In lobby: {0}", string.Join(",", cmpny.Passengers.Select(cpy => cpy.Name).ToArray())));
                if (plyr.PickUp.Count > 0)
                    log.Info(string.Format("       Pick-up: {0}", string.Join(",", plyr.PickUp.Select(psngr => psngr.Name).ToArray())));
            }

            // drop off if we have one and can do so
            PlayerAIBase.STATUS status = PlayerAIBase.STATUS.PASSENGER_NO_ACTION;
            Passenger psngrAbandoned = null;
            if (plyr.Passenger != null)
            {
                // Any enemies here?
                bool noDrop = cmpny.Passengers.Any(psngr => psngr.Lobby == cmpny && plyr.Passenger.Enemies.Contains(psngr));
                string msg;
                if (noDrop)
                {
                    status = PlayerAIBase.STATUS.PASSENGER_REFUSED;
                    msg = string.Format("Player {0} could not drop off passenger {1} at {2}", plyr.Name, plyr.Passenger.Name, cmpny.Name);
                    framework.StatusMessage(msg);
                }
                else if (plyr.Passenger.Destination == cmpny)
                {
                    msg = string.Format("Player {0} dropped off passenger {1} at {2}", plyr.Name, plyr.Passenger.Name, cmpny.Name);
                    framework.StatusMessage(msg);
                    plyr.Delivered(plyr.Passenger);
                    plyr.Passenger.Arrived(cmpny);
                    cmpny.Passengers.Add(plyr.Passenger);
                    plyr.Passenger = null;
                    status = PlayerAIBase.STATUS.PASSENGER_DELIVERED;
                }
                else
                {
                    msg = string.Format("Player {0} abandoned passenger {1} at {2}", plyr.Name, plyr.Passenger.Name, cmpny.Name);
                    framework.StatusMessage(msg);
                    psngrAbandoned = plyr.Passenger;
                    plyr.Passenger.Abandoned(cmpny);
                    cmpny.Passengers.Add(plyr.Passenger);
                    plyr.Passenger = null;
                    status = PlayerAIBase.STATUS.PASSENGER_ABANDONED;
                }
                if (log.IsInfoEnabled)
                    log.Info(msg);
            }

            // pick up if we have none (check because drop off may have been disallowed).
            // Can't be one we completed and can't be the one we dropped above.
            if (plyr.Passenger == null)
            {
                Passenger passenger = plyr.PickUp.FirstOrDefault(psngr => (psngr.Lobby == cmpny) && (psngr.Car == null) && (! plyr.PassengersDelivered.Contains(psngr)) && (psngr != psngrAbandoned));
                if (passenger != null)
                {
                    string msg = string.Format("Player {0} picked up passenger {1} at {2}", plyr.Name, passenger.Name, cmpny.Name);
                    if (log.IsInfoEnabled)
                        log.Info(msg);
                    framework.StatusMessage(msg);
                    passenger.EnterCar(plyr.Limo);
                    plyr.Passenger = passenger;
                    plyr.PickUp.Remove(passenger);
                    cmpny.Passengers.Remove(passenger);
                    status = status == PlayerAIBase.STATUS.PASSENGER_NO_ACTION ? PlayerAIBase.STATUS.PASSENGER_PICKED_UP : PlayerAIBase.STATUS.PASSENGER_DELIVERED_AND_PICKED_UP;
                }
            }

            if (log.IsInfoEnabled)
            {
                log.Info(string.Format("Player {0} exits bus stop {1} with {2}", plyr.Name, cmpny.Name, plyr.Passenger == null ? "{none}" : plyr.Passenger.Name));
                if (cmpny.Passengers.Count > 0)
                    log.Info(string.Format("       In lobby: {0}", string.Join(",", cmpny.Passengers.Select(cpy => cpy.Name).ToArray())));
                if (plyr.PickUp.Count > 0)
                    log.Info(string.Format("       Pick-up: {0}", string.Join(",", plyr.PickUp.Select(psngr => psngr.Name).ToArray())));
            }

            // Tell all players (and reset when next general status update will occur)
            framework.ticksSinceLastUpdate = 0;
            foreach (Player plyrOn in Players)
                plyrOn.GameStatus(null, plyr, status, Players, Passengers);
            if (!framework.FullSpeed)
            {
                framework.mainWindow.UpdatePlayers();
                framework.mainWindow.UpdateDebug();
            }
        }
示例#19
0
        /// <summary>
        /// Player is ready to start.
        /// </summary>
        /// <param name="player">The player. null if a join, non-null (maybe) if a re-join.</param>
        /// <param name="root">The XML message.</param>
        private void MsgPlayerReady(Player player, XElement root)
        {
            List<Point> path;
            List<Passenger> pickup;
            ReadMessage(player, root, out path, out pickup);
            GameEngine.RemoteMessages.Enqueue(new Engine.AiMessage(player, path, pickup));

            player.WaitingForReply = Player.COMM_MODE.RECEIVED_START;
            // if all ready (or all AI), we start
            if (engine.Players.All(pl => pl.WaitingForReply == Player.COMM_MODE.RECEIVED_START || pl.TcpGuid == null))
            {
                if (commState == COMM_STATE.ACCEPTING_JOINS || commState == COMM_STATE.ACCEPTING_SETUP)
                    commState = COMM_STATE.READY_TO_START;
                CommTimerClose();
                mainWindow.SetupGame();

                // test mode? If so we're good and so exit with code 0.
                if ((!string.IsNullOrEmpty(TestUser)) && player.Name == TestUser)
                {
                    tcpServer.SendMessage(player.TcpGuid, "<exit/>");
                    Thread.Sleep(100);
                    Environment.Exit(0);
                }

                if (DebugStartMode || AutoRunNumGames != 0)
                    Play();
            }
        }
示例#20
0
        /// <summary>
        /// Determine if any other limos are in this intersection.
        /// </summary>
        /// <param name="plyr">The player checking for. Ok if this player's car is in the intersection.</param>
        /// <param name="ptIntersection">The intersection tile. This is in tile units.</param>
        /// <param name="numFutureLook">How many steps into the future to look.</param>
        /// <returns></returns>
        private bool CarInIntersection(Player plyr, Point ptIntersection, int numFutureLook)
        {
            // bugbug numFutureLook (elsewhere too) depends on left/right/straight
            foreach (Player plyrOn in Players.Where(plyrOn => plyrOn != plyr))
            {
                // if they're more than the numFutureLook + limo size (Bitmap/2) away, then no need to walk as it can't match.
                if ((Math.Abs(plyr.Limo.Location.MapPosition.X - plyrOn.Limo.Location.MapPosition.X) > numFutureLook + TileMovement.UNITS_PER_TILE) ||
                                       (Math.Abs(plyr.Limo.Location.MapPosition.Y - plyrOn.Limo.Location.MapPosition.Y) > numFutureLook + TileMovement.UNITS_PER_TILE))
                    continue;

                // we walk numFutureLook (or till Future runs out) steps in the future to see if it's in the intersection.
                int stepsRemaining = numFutureLook;
                foreach (Limo.QuarterSteps stepOn in plyrOn.Limo.Future)
                {
                    if (BoardLocation.QuarterTileToTile(stepOn.QuarterLocation) == ptIntersection)
                    {
                        if (log.IsDebugEnabled)
                            log.Debug(string.Format("Player {0} : Player {1} Future in intersection {2}", plyr.Name, plyrOn.Name, ptIntersection));
                        return true;
                    }
                    stepsRemaining -= stepOn.Steps;
                    if (stepsRemaining <= 0)
                        break;
                }

                // checking the tail
                if (plyrOn.Limo.TailQuarter.Any(qtrOn => BoardLocation.QuarterTileToTile(qtrOn) == ptIntersection))
                {
                    // bus stop (or any u-turn), one car wants out, the other pulls in where it has 1 map unit tail still in the intersection.
                    // so if both vehicle center's are in the same tile AND they are in oppisate directions, then we say not in the intersection
                    var tile = MainMap.SquareOrDefault(ptIntersection).Tile;
                    if ((tile.Type == MapTile.TYPE.BUS_STOP) || (tile.Type == MapTile.TYPE.ROAD))
                        if (tile.Direction == MapTile.DIRECTION.NORTH_UTURN || tile.Direction == MapTile.DIRECTION.EAST_UTURN || tile.Direction == MapTile.DIRECTION.SOUTH_UTURN || tile.Direction == MapTile.DIRECTION.WEST_UTURN)
                        {
                            Trap.trap();
                            if (plyrOn.Limo.Location.Direction == MapSquare.UTurn(plyr.Limo.Location.Direction))
                            {
                                Trap.trap();
                                continue;
                            }
                            Trap.trap();
                        }

                    if (log.IsDebugEnabled)
                        log.Debug(string.Format("Player {0} : Player {1} Future in intersection {2}", plyr.Name, plyrOn.Name, ptIntersection));
                    return true;
                }
                if (log.IsDebugEnabled)
                    log.Debug(string.Format("Player {0} : Player {1} NOT in intersection {2}", plyr.Name, plyrOn.Name, ptIntersection));
            }
            return false;
        }
示例#21
0
        /// <summary>
        /// Called when the game starts, providing all info.
        /// </summary>
        /// <param name="map">The game map.</param>
        /// <param name="me">The player being setup..</param>
        /// <param name="players">All the players.</param>
        /// <param name="companies">All companies on the board.</param>
        /// <param name="passengers">All the passengers.</param>
        /// <param name="ordersEvent">Callback to pass orders to the engine.</param>
        public void Setup(GameMap map, Player me, List<Player> players, List<Company> companies, List<Passenger> passengers, PlayerAIBase.PlayerOrdersEvent ordersEvent)
        {
            // start the thread
            aiWorker = new AiWorker(map, me.Guid, companies, ordersEvent);
            aiThread = new Thread(aiWorker.MainLoop) {Name = me.Name.Replace(' ', '_'), IsBackground = true};
            aiThread.Start();

            // cause it to pick a passenger to pick up and calculate the path to that company.
            aiWorker.AddMessage(PlayerAIBase.STATUS.NO_PATH, me, AllPickups(me, passengers));
        }
示例#22
0
        /// <summary>
        /// Move the limo.
        /// </summary>
        /// <param name="plyr">The player who's limo is being moved.</param>
        /// <param name="signalsSet">Tiles where the signal has had it's value set/locked.</param>
        /// <param name="lastPass">true if last pass. Any slow down or stopping occurs this time.</param>
        private void MoveLimo(Player plyr, List<Point> signalsSet, bool lastPass)
        {
            bool isDebugEnabled = log.IsDebugEnabled; // 4.7% of total CPU time when called in each case here.
            if (isDebugEnabled)
                log.Debug(string.Format("{0} : MoveLimo, speed = {1}, accrued = {2}, steps = {3}, location = {4}", plyr.Name, plyr.Limo.Speed, plyr.Limo.AccruedSteps, plyr.Limo.StepsRemaining, plyr.Limo.Location));

            // if stuck, un-stick it
            if (plyr.Limo.NumTurnsStopped >= Limo.MAX_TURNS_STOPPED)
            {
                plyr.Limo.Accelerate();
                plyr.Limo.IsForceMove = true;
                plyr.Limo.StepsRemaining = TileMovement.MAX_STRAIGHT_SPEED;
            }
            else
                plyr.Limo.IsForceMove = false;

            // once for each step on this tick
            while (plyr.Limo.StepsRemaining > 0)
            {
                // there's the point that the center of the sprite is on - actual movement goes from that
                // plyr.Limo.Location is map & tile on.
                Point ptCenterNextMapPos = plyr.Limo.Location.NextPosition;

                // there's the point the front of the sprite is at - stop signs and traffic go from that.
                Point ptFrontMapPos = plyr.Limo.Front;
                Point ptFrontTile = BoardLocation.MapToTile(ptFrontMapPos);
                Point ptFrontNextMapPos = plyr.Limo.FrontNextStep;
                Point ptFrontNextTile = BoardLocation.MapToTile(ptFrontNextMapPos);
                if (isDebugEnabled)
                    log.Debug(string.Format("{0} : MoveLimo, ptFront = {1} ({2}), ptNext = {3} ({4})", plyr.Name, ptFrontMapPos, ptFrontTile, ptFrontNextMapPos, ptFrontNextTile));

                MapSquare square = MainMap.Squares[ptFrontNextTile.X][ptFrontNextTile.Y];
                MapSquare.COMPASS_DIRECTION direction = plyr.Limo.Location.Direction;

                // stop sign or red light - we stop. Only test when we would enter the tile (once in, you don't stop!)
                if ((! plyr.Limo.IsForceMove) && (ptFrontTile != ptFrontNextTile))
                {
                    bool isStop = square.IsStop(direction);
                    int limoHalfLength = plyr.Limo.VehicleBitmap.Height / 4 + 1;

                    // signal - turn green if allowed. Otherwise request green and it will go yellow the other way.
                    if (square.SignalDirection != MapSquare.SIGNAL_DIRECTION.NONE)
                    {
                        // the /2 for half length and the other /2 because map units are 1/2 sprite units.
                        bool carInInter = CarInIntersection(plyr, ptFrontNextTile, limoHalfLength);

                        // We have to lock the signal once it is used. Otherwise car #1 gets a green and car #2 flips it to the other direction.
                        bool signalLocked = signalsSet.Contains(ptFrontNextTile);

                        // if the signal is not locked and we can only flip to yellow, wait in case the car will move out
                        if ((!signalLocked) && carInInter && (!lastPass))
                        {
                            if (isDebugEnabled)
                                log.Debug(string.Format("{0} : see if signal opens up, location = {1}", plyr.Name, plyr.Limo.Location));
                            return;
                        }

                        // if the signal has not been locked yet, lock it.
                        // we are here even if we are not stopped (have a green) - because we need to lock in the green.
                        if (!signalLocked)
                            signalsSet.Add(ptFrontNextTile);

                        // if this is the first on this square, then we can set the signal.
                        if (isStop && (!signalLocked))
                        {
                            if (carInInter)
                            {
                                // flip it to yellow so we get it when the car in there exits.
                                switch (direction)
                                {
                                    case MapSquare.COMPASS_DIRECTION.NORTH:
                                    case MapSquare.COMPASS_DIRECTION.SOUTH:
                                        square.SignalDirection = MapSquare.SIGNAL_DIRECTION.EAST_WEST_YELLOW;
                                        break;
                                    case MapSquare.COMPASS_DIRECTION.EAST:
                                    case MapSquare.COMPASS_DIRECTION.WEST:
                                        square.SignalDirection = MapSquare.SIGNAL_DIRECTION.NORTH_SOUTH_YELLOW;
                                        break;
                                }
                            }
                            else
                            {
                                // all ours - flip to green (may already be green) and keep going
                                isStop = false;
                                switch (direction)
                                {
                                    case MapSquare.COMPASS_DIRECTION.NORTH:
                                    case MapSquare.COMPASS_DIRECTION.SOUTH:
                                        square.SignalDirection = MapSquare.SIGNAL_DIRECTION.NORTH_SOUTH_GREEN;
                                        break;
                                    case MapSquare.COMPASS_DIRECTION.EAST:
                                    case MapSquare.COMPASS_DIRECTION.WEST:
                                        square.SignalDirection = MapSquare.SIGNAL_DIRECTION.EAST_WEST_GREEN;
                                        break;
                                }
                            }
                            if (isDebugEnabled)
                                log.Debug(string.Format("{0} : signal at {1} flipped to {2}", plyr.Name, ptFrontNextTile, square.SignalDirection));
                        }
                    }

                    // see if we can go again.
                    if (isStop && (square.StopSigns != MapSquare.STOP_SIGNS.NONE) && (plyr.Limo.IsStopped))
                    {
                        bool carInInter = CarInIntersection(plyr, ptFrontNextTile, limoHalfLength + TileMovement.NUM_UNITS_CROSS_ROAD);
                        if (!carInInter)
                        {
                            isStop = false;
                            plyr.Limo.Go();
                        }

                        // wait and see if it clears out.
                        if (isStop && (! lastPass))
                        {
                            if (isDebugEnabled)
                                log.Debug(string.Format("{0} : see if stop opens up, location = {1}", plyr.Name, plyr.Limo.Location));
                            ValidateData(plyr);
                            return;
                        }
                    }

                    // stop signs will always have this true
                    if (isStop)
                    {
                        plyr.Limo.Stop();
                        if (isDebugEnabled)
                            log.Debug(string.Format("{0} : STOP, location = {1}", plyr.Name, plyr.Limo.Location));
                        ValidateData(plyr);
                        return;
                    }

                    // if we're making a left turn in an intersection, we have to look at future of other cars. We can only do this if they have
                    // a path because the random direction is selected when the center croses into the new tile.
                    if (plyr.Limo.PathTiles.Count > 0)
                        switch (square.Tile.Direction)
                        {
                            case MapTile.DIRECTION.INTERSECTION:
                            case MapTile.DIRECTION.T_NORTH:
                            case MapTile.DIRECTION.T_EAST:
                            case MapTile.DIRECTION.T_SOUTH:
                            case MapTile.DIRECTION.T_WEST:
                                Point ptNext = plyr.Limo.PathTiles[0];
                                int indPath = 1;
                                if (ptNext == ptFrontTile && indPath < plyr.Limo.PathTiles.Count)
                                    ptNext = plyr.Limo.PathTiles[indPath++];
                                if (ptNext == ptFrontNextTile && indPath < plyr.Limo.PathTiles.Count)
                                    ptNext = plyr.Limo.PathTiles[indPath];
                                if (ptFrontNextTile == ptNext)
                                {
                                    if (isDebugEnabled)
                                        log.Debug(string.Format("{0} : ptFrontNextTile == ptNext == {1} (count = {2}", plyr.Name, ptNext, plyr.Limo.PathTiles.Count));
                                    break;
                                }
                                MapSquare.COMPASS_DIRECTION dirEnter = MapSquare.PointsDirection(ptFrontTile, ptFrontNextTile);
                                MapSquare.COMPASS_DIRECTION dirExit = MapSquare.PointsDirection(ptFrontNextTile, ptNext);
                                // fast exit for straight
                                if (dirEnter == dirExit)
                                    break;
                                // exit if right turn
                                if ((dirEnter != MapSquare.COMPASS_DIRECTION.NORTH || dirExit != MapSquare.COMPASS_DIRECTION.WEST) &&
                                    (dirEnter != MapSquare.COMPASS_DIRECTION.EAST || dirExit != MapSquare.COMPASS_DIRECTION.NORTH) &&
                                    (dirEnter != MapSquare.COMPASS_DIRECTION.SOUTH || dirExit != MapSquare.COMPASS_DIRECTION.EAST) &&
                                    (dirEnter != MapSquare.COMPASS_DIRECTION.WEST || dirExit != MapSquare.COMPASS_DIRECTION.SOUTH))
                                    break;

                                // ok it's a left or U turn - need to check oncoming traffic
                                if (isDebugEnabled)
                                    log.Debug(string.Format("{0} : making left turn {1} to {2} (ptNext = {3})", plyr.Name, dirEnter, dirExit, ptNext));

                                // check the future of other cars - see if it is anywhere in the square. Distance is MaxTileSteps steps through the curve
                                // at speed MAX_CURVE_SPEED while the oncoming is at MAX_STRAIGHT_SPEED. Plus the car from center to front * 3/4 for car plus space between
                                int safeDistance = (plyr.Limo.VehicleBitmap.Height * 3) / 4 + 1 +
                                                   ((TileMovement.MAX_TILE_STEPS + TileMovement.MAX_CURVE_SPEED - 1) / TileMovement.MAX_CURVE_SPEED) * TileMovement.MAX_STRAIGHT_SPEED;
                                foreach (Player plyrOn in Players.Where(plyrOn => plyrOn != plyr))
                                {
                                    // if they're more than the Limo.NUM_FUTURE away, then no need to walk as it can't match.
                                    if ((Math.Abs(plyr.Limo.Location.MapPosition.X - plyrOn.Limo.Location.MapPosition.X) > safeDistance + TileMovement.UNITS_PER_TILE) ||
                                                        (Math.Abs(plyr.Limo.Location.MapPosition.Y - plyrOn.Limo.Location.MapPosition.Y) > safeDistance + TileMovement.UNITS_PER_TILE))
                                        continue;
                                    // if they're stopped, not an issue
                                    if (plyrOn.Limo.IsStopped && BoardLocation.MapToTile(plyrOn.Limo.Front) != ptFrontNextTile)
                                    {
                                        if (isDebugEnabled)
                                            log.Debug(string.Format("{0} : player {1} limo stopped - ignore for turn check", plyr.Name, plyrOn.Name));
                                        continue;
                                    }

                                    // see if anyone's future goes into this quarter tile (we use quarter tiles for collision detection).
                                    int numSteps = safeDistance;
                                    if (isDebugEnabled)
                                        log.Debug(string.Format("{0} : check {1} oncoming into tile {2}, safeDist = {3}", plyr.Name, plyrOn.Name, ptFrontNextTile, safeDistance));

                                    // we first check for the cent of the limo in this tile. This handles cars turning (which will end up cross and not catch in the below foreach).
                                    // this also handles any case of any car in the intersection for any reason - we don't turn then because that would be a conflict for an
                                    // outer curve (exception being an inverse inner curve - but tough).
                                    bool waitForOncoming = plyrOn.Limo.Location.TilePosition == ptFrontNextTile;

                                    if (! waitForOncoming)
                                        foreach (Limo.QuarterSteps stepOn in plyrOn.Limo.Future)
                                        {
                                            if (isDebugEnabled)
                                                log.Debug(string.Format("{0} : stepOn = {1} ({2})", plyr.Name, stepOn,
                                                                        BoardLocation.QuarterTileToTile(stepOn.QuarterLocation)));
                                            if (BoardLocation.QuarterTileToTile(stepOn.QuarterLocation) == ptFrontNextTile)
                                            {
                                                // they must be coming from the opposite direction to matter. If coming from the left/right
                                                // they are going to hit a signal or stoplight. We need the next tile out to get direction (next quarter tile can be diaganol).
                                                Point ptCenterPlyrOn = plyrOn.Limo.Location.TilePosition;
                                                MapSquare.COMPASS_DIRECTION dirPlyrOn = MapSquare.COMPASS_DIRECTION.NONE;
                                                foreach (Limo.QuarterSteps qs in plyrOn.Limo.Future)
                                                {
                                                    Point ptFutureTile = BoardLocation.QuarterTileToTile(qs.QuarterLocation);
                                                    if (ptFutureTile != ptCenterPlyrOn)
                                                    {
                                                        dirPlyrOn = MapSquare.PointsDirection(ptCenterPlyrOn, ptFutureTile);
                                                        break;
                                                    }
                                                }
                                                Trap.trap(dirPlyrOn == MapSquare.COMPASS_DIRECTION.NONE);
                                                if (dirPlyrOn != MapSquare.COMPASS_DIRECTION.NONE && MapSquare.UTurn(dirPlyrOn) != dirEnter)
                                                {
                                                    if (isDebugEnabled)
                                                        log.Debug(string.Format("{0} : player {1} dir from side {2} - ignore for turn check", plyr.Name,
                                                                                plyrOn.Name, dirPlyrOn));
                                                    break;
                                                }
                                                waitForOncoming = true;
                                                break;
                                            }

                                            // see if gone enough steps
                                            numSteps -= stepOn.Steps;
                                            if (numSteps <= 0)
                                                break;
                                        }

                                    if (!waitForOncoming)
                                        continue;

                                    // wait and see if it moves
                                    if ((!lastPass) && (plyrOn.Limo.StepsRemaining > 0))
                                    {
                                        if (isDebugEnabled)
                                            log.Debug(string.Format("{0} : left turn wait - behind {1}, location = {2}", plyr.Name, plyrOn.Name,
                                                                    plyrOn.Limo.Location));
                                        ValidateData(plyr);
                                        return;
                                    }

                                    // need to stop
                                    plyr.Limo.Stop();
                                    if (isDebugEnabled)
                                        log.Debug(string.Format("{0} : left turn stop because of {1}, location = {2}", plyr.Name, plyrOn.Name,
                                                                plyrOn.Limo.Location));
                                    ValidateData(plyr);
                                    return;
                                }
                                break;
                        }
                    else
                        if (isDebugEnabled)
                            log.Debug(string.Format("{0} : path.count == 0", plyr.Name));
                }

                // is there anyone in our way? 1.5 is center to front plus 1 car length. Additional /2 is because map units are 1/2 sprite units.
                if (!plyr.Limo.IsForceMove)
                {
                    int safeDistance = (plyr.Limo.VehicleBitmap.Height*3)/4 + 1;
                    foreach (Player plyrOn in Players.Where(plyrOn => plyrOn != plyr))
                    {
                        // if they're more than the Limo.NUM_FUTURE + Limo.NUM_TAIL away, then no need to walk as it can't match.
                        if ((Math.Abs(plyr.Limo.Location.MapPosition.X - plyrOn.Limo.Location.MapPosition.X) > Limo.NUM_FUTURE + Limo.NUM_TAIL + TileMovement.UNITS_PER_TILE) ||
                                        (Math.Abs(plyr.Limo.Location.MapPosition.Y - plyrOn.Limo.Location.MapPosition.Y) > Limo.NUM_FUTURE + Limo.NUM_TAIL + TileMovement.UNITS_PER_TILE))
                            continue;

                        // see if we hit anyone's tail with our future
                        int stepsRemaining = safeDistance;
                        foreach (Limo.QuarterSteps stepOn in plyr.Limo.Future)
                        {
                            // see if both are in the same quarter tile. We use quarter tiles for collision detection.
                            if (plyrOn.Limo.TailQuarter.Contains(stepOn.QuarterLocation))
                            {
                                // wait and see if it moves
                                if ((!lastPass) && (plyrOn.Limo.StepsRemaining > 0))
                                {
                                    if (isDebugEnabled)
                                        log.Debug(string.Format("{0} : wait - behind {1}, location = {2}", plyr.Name, plyrOn.Name, plyrOn.Limo.Location));
                                    ValidateData(plyr);
                                    return;
                                }

                                // next turn will +0.5 so this will have a final affect of -0.5
                                plyr.Limo.Decelerate();
                                plyr.Limo.NumTurnsStopped++;
                                if (isDebugEnabled)
                                    log.Debug(string.Format("{0} : stuck behind {1}, location = {2}", plyr.Name, plyrOn.Name, plyrOn.Limo.Location));
                                ValidateData(plyr);
                                return;
                            }

                            // see if we've walked far enough.
                            stepsRemaining -= stepOn.Steps;
                            if (stepsRemaining <= 0)
                                break;
                        }
                    }
                }

                // if the next center position is in the same tile, we can move along the offset
                if (plyr.Limo.Location.IsMoveInsideTile)
                {
                    plyr.Limo.Move();
                    plyr.Limo.StepsRemaining--;
                    if (isDebugEnabled)
                        log.Debug(string.Format("{0} : move within tile, location = {1}", plyr.Name, plyr.Limo.Location));
                    Trap.trap(ptCenterNextMapPos != plyr.Limo.Location.MapPosition);
                    ValidateData(plyr);

                    // have we arrived at a bus stop - needs to be the center point.
                    Point ptCenterTile = plyr.Limo.Location.TilePosition;
                    MapSquare squareCenter = MainMap.Squares[ptCenterTile.X][ptCenterTile.Y];
                    if ((squareCenter.Tile.Type == MapTile.TYPE.BUS_STOP) && (plyr.Limo.Location.OffsetTileMoves == plyr.Limo.Location.TileMoves.Moves.Length / 2))
                    {
                        BusStopOffOn(plyr, ptCenterTile);
                        plyr.Limo.Stop();
                        plyr.Limo.Go();
                        if (isDebugEnabled)
                            log.Debug(string.Format("{0} : bus stop processed limo = {1}", plyr.Name, plyr.Limo));
                        Trap.trap(ptCenterNextMapPos != plyr.Limo.Location.MapPosition);
                        ValidateData(plyr);
                    }
                    continue;
                }

                // we may be holding the tile we're on in the path. If so, get rid of it. (Generally occurs when given a new path.)
                if ((plyr.Limo.PathTiles.Count > 0) && (plyr.Limo.PathTiles[0] == plyr.Limo.Location.TilePosition))
                    plyr.Limo.PathTiles.RemoveAt(0);

                // we move to the next spot (start of next tile), then below assign movement within the tile
                plyr.Limo.Move();
                plyr.Limo.StepsRemaining--;
                if (isDebugEnabled)
                    log.Debug(string.Format("{0} : move 1 prep for next tile, location = {1}", plyr.Name, plyr.Limo.Location));
                Trap.trap(plyr.Limo.Location.OffsetTileMoves != plyr.Limo.Location.TileMoves.Moves.Length);
                Trap.trap(ptCenterNextMapPos != plyr.Limo.Location.MapPosition);

                // we now work with the next position because that moves us into the next tile if we are at offset 0 and going north or west.
                // this has to be the next map position converted to tile position because that is sometimes this tile position, sometimes next.
                ptCenterNextMapPos = plyr.Limo.Location.NextPosition;
                Point ptCenterNextTile = BoardLocation.MapToTile(ptCenterNextMapPos);

                // discard next tile(s) - if it has it and if it's the one we're entering.
                int indexPath = plyr.Limo.PathTiles.FindIndex(pt => pt == ptCenterNextTile);
                if (indexPath != -1)
                    plyr.Limo.PathTiles.RemoveRange(0, indexPath + 1);

                // get our new destination - from the path if valid
                MapSquare.COMPASS_DIRECTION destDirection = MapSquare.COMPASS_DIRECTION.NONE;
                if (plyr.Limo.PathTiles.Count > 0)
                {
                    int x = plyr.Limo.PathTiles[0].X - ptCenterNextTile.X;
                    int y = plyr.Limo.PathTiles[0].Y - ptCenterNextTile.Y;
                    if (Math.Abs(x) + Math.Abs(y) == 1)
                    {
                        if (MainMap.Squares[plyr.Limo.PathTiles[0].X][plyr.Limo.PathTiles[0].Y].Tile.IsDriveable)
                        {
                            destDirection = MapSquare.PointsDirection(ptCenterNextTile, plyr.Limo.PathTiles[0]);
                            if (isDebugEnabled)
                                log.Debug(string.Format("{0} : {1} = {2} - {3}", plyr.Name, destDirection, ptCenterNextTile, plyr.Limo.PathTiles[0]));
                        }
                        else
                        {
                            Trap.trap();
                            plyr.GameStatus(null, plyr, PlayerAIBase.STATUS.NO_PATH, Players, Passengers);
                            plyr.Limo.PathTiles.Clear();
                        }
                    }
                }

                // need to grab one of the exit tiles at random. U-turn only if no alternative
                if (destDirection == MapSquare.COMPASS_DIRECTION.NONE)
                {
                    destDirection = square.Tile.GetRandomNext(direction);
                    if (isDebugEnabled)
                        log.Debug(string.Format("{0} : {1} = GetRandomNext({2})", plyr.Name, destDirection, direction));
                }

                // get the inter-tile movement and assign
                TileMovement movement = TileMovement.GetMove(direction, destDirection);
                plyr.Limo.Location.SetMapPosition(plyr.Limo.Location.MapPosition, movement);

                // do we have to slow down?
                if (plyr.Limo.Location.TileMoves.MaxSpeed < plyr.Limo.Speed)
                {
                    float diff = plyr.Limo.Speed - plyr.Limo.Location.TileMoves.MaxSpeed;
                    plyr.Limo.Speed = plyr.Limo.Location.TileMoves.MaxSpeed;
                    plyr.Limo.StepsRemaining = Math.Max(0, plyr.Limo.StepsRemaining - (int) (diff + 0.9f));
                }

                if (isDebugEnabled)
                    log.Debug(string.Format("{0} : next tile complete, location = {1}", plyr.Name, plyr.Limo.Location));
                ValidateData(plyr);
            }
        }
示例#23
0
 public void AddMessage(PlayerAIBase.STATUS status, Player about, List<Passenger> pickup)
 {
     StatusMessage msg = new StatusMessage(status, about, pickup);
     lock (messages)
         messages.Enqueue(msg);
     EventThread.Set();
 }
示例#24
0
        /// <summary>
        /// Calculates the estimated path for each limo. Resets count of steps taken. Adjusts speed.
        /// </summary>
        /// <param name="plyr">The player being reset for the move.</param>
        private void PrepareToMove(Player plyr)
        {
            if (log.IsDebugEnabled)
                log.Debug(string.Format("{0} : PrepareToMove, location = {1}", plyr.Name, plyr.Limo.Location));

            plyr.Limo.Future.Clear();
            Point ptOn = plyr.Limo.Location.MapPosition;
            Point ptMapStart = BoardLocation.MapToTile(ptOn);
            plyr.Limo.AddFuture(ptOn);
            BoardLocation location = new BoardLocation(plyr.Limo.Location);
            int pathOffset = 0;

            for (int ind = 0; ind < Limo.NUM_FUTURE; ind++)
            {
                if (location.IsMoveInsideTile)
                {
                    location.Move();
                    plyr.Limo.AddFuture(location.MapPosition);
                    continue;
                }

                // get where we enter the next tile
                Point ptNextMap = location.NextPosition;
                Point ptNextTile = location.NextTilePosition;
                MapSquare squareNext = MainMap.Squares[ptNextTile.X][ptNextTile.Y];
                MapSquare.COMPASS_DIRECTION dirOn = location.Direction;

                // if we enter a stop or signal, we're done guessing the future. We've actually moved the car half way into the
                // intersection in this case. But it's more efficient than getting the front location each step and
                // we need the path up to the tile edge.
                // We go on a signal regardless of color because it can be green when we get there and this is used to see if cars
                // the other way can turn left.
                if (ptNextTile != ptMapStart)
                {
                    if (squareNext.IsStopAllGreen(dirOn))
                    {
                        if (log.IsDebugEnabled)
                            log.Debug(string.Format("{0} : PrepareToMove hit stop at = {1}, {2}", plyr.Name, ptNextTile, dirOn));
                        break;
                    }
                    // might be a u-turn
                    ptMapStart = Point.Empty;
                }

                // move into the next tile - so below calculations are based on the tile we've just entered (but can now move through in any direction).
                location.Move();
                plyr.Limo.AddFuture(location.MapPosition);

                // we now work with the next position because that moves us into the next tile if we are at offset 0 and going north or west.
                // this has to be the next map position converted to tile position because that is sometimes this tile position, sometimes next.
                Trap.trap(location.MapPosition != ptNextMap);
                ptNextMap = location.NextPosition;
                ptNextTile = BoardLocation.MapToTile(ptNextMap);

                // we increment it here because a U-turn does not move to the next tile and we need the same offset again.
                if ((pathOffset < plyr.Limo.PathTiles.Count) && (plyr.Limo.PathTiles[pathOffset] == ptNextTile))
                    pathOffset++;

                // get our new destination - from the path if valid
                MapSquare.COMPASS_DIRECTION destDirection = MapSquare.COMPASS_DIRECTION.NONE;
                if (plyr.Limo.PathTiles.Count > pathOffset)
                {
                    int x = plyr.Limo.PathTiles[pathOffset].X - ptNextTile.X;
                    int y = plyr.Limo.PathTiles[pathOffset].Y - ptNextTile.Y;
                    if (Math.Abs(x) + Math.Abs(y) == 1)
                        destDirection = MapSquare.PointsDirection(ptNextTile, plyr.Limo.PathTiles[pathOffset]);
                    else
                        if (log.IsDebugEnabled)
                            log.Debug(string.Format("{0} : PrepareToMove path error at = {1}, {2}; pathOff={3}, count={4}; x={5}, y={6}", plyr.Name, ptNextTile, dirOn, pathOffset, plyr.Limo.PathTiles.Count, x, y));
                }

                // if no path, we get the next one only if just one choice (straight/curves) or straight is allowed.
                // in other words, entering the top of a T we assume straight across. Entering from the base we stop (returns NONE).
                if (destDirection == MapSquare.COMPASS_DIRECTION.NONE)
                    destDirection = squareNext.Tile.GetStraightNext(dirOn);
                if (destDirection == MapSquare.COMPASS_DIRECTION.NONE)
                {
                    if (log.IsDebugEnabled)
                        log.Debug(string.Format("{0} : PrepareToMove no dirNext at = {1}, {2}; pathOff={3}, count={4}", plyr.Name, ptNextTile, dirOn, pathOffset, plyr.Limo.PathTiles.Count));
                    break;
                }

                // get the inter-tile movement and assign
                TileMovement movement = TileMovement.GetMove(dirOn, destDirection);
                location.SetMapPosition(location.MapPosition, movement);
                if (log.IsDebugEnabled)
                    log.Debug(string.Format("{0} : PrepareToMove next tile complete, location = {1}", plyr.Name, location));
            }

            if (log.IsDebugEnabled)
            {
                if (plyr.Limo.Future.Count == 0)
                    log.Debug(string.Format("{0} : PrepareToMove complete, future, len=0", plyr.Name));
                else
                    log.Debug(string.Format("{0} : PrepareToMove complete, future = {1}..{2}, len={3}", plyr.Name,
                                        plyr.Limo.Future[0], plyr.Limo.Future[plyr.Limo.Future.Count - 1], plyr.Limo.Future.Count));
            }
        }
示例#25
0
 public PlayerInfo(Player src)
 {
     Trap.trap();
     Guid = src.Guid;
 }
示例#26
0
        /// <summary>
        /// Call the AI with a status message.
        /// </summary>
        /// <param name="xmlMessage">Can be null. The remote AI XML for a message without the status or my player values set.</param>
        /// <param name="about">The player this status is about. Will be set to receiving user for status not specific to a player.</param>
        /// <param name="status">The status for this message.</param>
        /// <param name="players">All the players.</param>
        /// <param name="passengers">All the passengers.</param>
        public void GameStatus(XDocument xmlMessage, Player about, PlayerAIBase.STATUS status, List<Player> players, List<Passenger> passengers)
        {
            if (TcpGuid == null)
                return;

            if (xmlMessage == null)
                xmlMessage = BuildMessageXml(players, passengers);
            XAttribute attr = xmlMessage.Root.Attribute("status");
            if (attr == null)
                xmlMessage.Root.Add(new XAttribute("status", status));
            else
                attr.Value = status.ToString();

            attr = xmlMessage.Root.Attribute("player-guid");
            if (attr == null)
                xmlMessage.Root.Add(new XAttribute("player-guid", about.Guid));
            else
                attr.Value = about.Guid;

            StringBuilder buf = new StringBuilder();
            Player player = framework.GameEngine.Players.Find(pl => pl.TcpGuid == TcpGuid);
            if (player != null)
                foreach (Point ptOn in player.Limo.PathTiles)
                    buf.Append(Convert.ToString(ptOn.X) + ',' + Convert.ToString(ptOn.Y) + ';');

            XElement elem = xmlMessage.Root.Element("path");
            if (elem == null)
            {
                elem = new XElement("path");
                xmlMessage.Root.Add(elem);
                elem.Value = buf.ToString();
            }
            else
                elem.Value = buf.ToString();

            if (player != null)
            {
                buf.Clear();
                foreach (Passenger psngr in player.PickUp)
                    buf.Append(psngr.Name + ';');
            }
            elem = xmlMessage.Root.Element("pick-up");
            if (elem == null)
            {
                elem = new XElement("pick-up");
                xmlMessage.Root.Add(elem);
                elem.Value = buf.ToString();
            }
            else
                elem.Value = buf.ToString();

            framework.tcpServer.SendMessage(TcpGuid, xmlMessage.ToString());
        }