Esempio n. 1
0
            public void Update(CtfGameState state, Team yourTeam, IList<Team> enemyTeams)
            {
                var enemy = enemyTeams[0];
                foreach (var ship in yourTeam.Ships)
                {
                    if (Math.Round(m_rand.NextDouble()) == 0)
                    {
                        ship.Fire();
                    }
                    else
                    {
                        ship.StopFiring();
                    }

                    ship.SetThrust((float)m_rand.NextDouble());

                    var t = enemy.Flag.HeldBy == ship.Id ? yourTeam.Flag.Position : yourTeam.Flag.HeldBy != null ? yourTeam.Flag.Position : enemy.Flag.Position;
                    Vector2 target = Vector2.Normalize(t - ship.Position);
                    if (!(float.IsNaN(target.X) && float.IsNaN(target.Y)))
                    {
                        float d = (float)Math.Atan2(target.Y, target.X) - (ship.Rotation + (ship.AngularVelocity * 5));
                        ship.SetTorque(Math.Sign(d));
                    }
                }
            }
Esempio n. 2
0
        private CtfGameState Step(CtfGameState state)
        {
            CtfGameState newState = state.Clone();

            newState.TurnNumber++;

            foreach (var team in newState.Teams)
            {
                StepTeam(team);
            }

            return(newState);
        }
Esempio n. 3
0
        /// <summary>
        /// Create a ctf game
        /// </summary>
        /// <param name="rules">The rules of this game</param>
        /// <param name="ais">All AIs that will be competing in this game</param>
        public CtfGame(CtfGameRules rules, IList <ICtfAi> ais)
        {
            if (rules == null)
            {
                throw new ArgumentNullException("rules");
            }

            if (ais == null)
            {
                throw new ArgumentNullException("ais");
            }

            SpawnPositions = new Dictionary <int, Vector2>();
            Rules          = rules;
            States         = new List <CtfGameState>(Rules.TurnLimit);

            //Calculate spacing of objects for spawn positions
            float teamSpacing = MathHelper.TwoPi / ais.Count;
            float shipSpacing = MathHelper.TwoPi / Rules.ShipsPerTeam;

            float flagRadius = Rules.ArenaRadius - (2 * Rules.ShipRadius) - Rules.FlagRadius;

            CtfGameState initialState = new CtfGameState();

            initialState.Teams = new List <Team>(ais.Count);
            int teamIndex = 0;

            //Initialise all the teams
            foreach (ICtfAi ai in ais)
            {
                var team = new Team()
                {
                    Name = ai.Name ?? "Unnamed AI"
                };

                team.Flag = new Flag()
                {
                    Bounds = new BoundingCircle(Vector2.FromPolar(flagRadius, teamSpacing * teamIndex), Rules.FlagRadius),
                    Owner  = team.Id,
                };
                SpawnPositions[team.Flag.Id] = team.Flag.Position;

                m_ais[team.Id] = ai;

                team.Ships = new List <Ship>();

                for (int i = 0; i < rules.ShipsPerTeam; i++)
                {
                    var ship = new Ship()
                    {
                        Bounds   = new BoundingCircle(team.Flag.Position + Vector2.FromPolar(Rules.FlagRadius + Rules.ShipRadius, i * shipSpacing), Rules.ShipRadius),
                        Owner    = team.Id,
                        Rotation = (i * shipSpacing),
                    };

                    SpawnPositions[ship.Id]  = ship.Position;
                    m_lastFireTurns[ship.Id] = int.MinValue + 1;

                    team.Ships.Add(ship);
                }

                team.Projectiles = new List <Projectile>();

                initialState.Teams.Add(team);

                teamIndex++;
            }

            States.Add(initialState);
            m_currentState = initialState;
        }
Esempio n. 4
0
        /// <summary>
        /// Advance the game by one turn
        /// </summary>
        public void Step()
        {
            if (IsGameOver)
            {
                return;
            }

            //Check for win condition
            if (States.Count == Rules.TurnLimit || m_currentState.Teams.Any(t => t.FlagCaptures == Rules.FlagLimit))
            {
                var winningTeam = m_currentState.Teams.OrderByDescending(t => t.FlagCaptures).ThenByDescending(t => t.Kills).FirstOrDefault();

                if (States.Count == Rules.TurnLimit)
                {
                    GameEndReason = "Turn limit reached";
                }
                else if (m_currentState.Teams.Any(t => t.FlagCaptures == Rules.FlagLimit))
                {
                    GameEndReason = string.Format("AI {0} ({1}) reached the flag capture limit", winningTeam.Name, winningTeam.Id);
                }

                m_currentState.Events.Add(GameEndReason);

                WinningTeam = winningTeam.Id;

                return;
            }

            IDictionary <int, Ship>         masterShips = m_currentState.Teams.SelectMany(t => t.Ships).ToDictionary(s => s.Id);
            IDictionary <int, Team>         masterTeams = m_currentState.Teams.ToDictionary(t => t.Id);
            IDictionary <int, CtfGameState> updates     = new Dictionary <int, CtfGameState>();
            HashSet <int> deadProjectiles = new HashSet <int>();

            //Resolve collisions
            foreach (var team in masterTeams.Values)
            {
                foreach (var projectile in team.Projectiles)
                {
                    if (deadProjectiles.Contains(projectile.Id))
                    {
                        //Check if this projectile was previously hit by another projectile
                        continue;
                    }

                    //Remove projectiles that go out of bounts
                    if (projectile.Position.Length() > Rules.ArenaRadius)
                    {
                        deadProjectiles.Add(projectile.Id);
                        continue;
                    }

                    foreach (var enemyTeam in masterTeams.Values)
                    {
                        if (team.Id == enemyTeam.Id)
                        {
                            continue;
                        }

                        foreach (var enemyShip in enemyTeam.Ships)
                        {
                            if (enemyShip.Bounds.Intersects(projectile.Bounds))
                            {
                                string killLog = string.Format("{0}'s ship ({1}) was killed by {2}'s ship ({3})", enemyTeam.Name, enemyShip.Id, team.Name, masterShips[projectile.FiredBy].Id);
                                m_currentState.Events.Add(killLog);

                                //Ship hit
                                deadProjectiles.Add(projectile.Id);
                                enemyShip.Position = SpawnPositions[enemyShip.Id];
                                team.Kills++;

                                //Reset flag position if the killed ship was holding a flag
                                foreach (var t in masterTeams.Values)
                                {
                                    if (t.Flag.HeldBy == enemyShip.Id)
                                    {
                                        string dropLog = string.Format("{0}'s flag was dropped by {1}'s ship ({2}) after it was killed", masterTeams[t.Flag.Owner].Name, enemyTeam.Name, enemyShip.Id);
                                        m_currentState.Events.Add(dropLog);
                                        t.Flag.HeldBy   = null;
                                        t.Flag.Position = SpawnPositions[team.Flag.Id];
                                    }
                                }

                                continue;
                            }
                        }

                        if (deadProjectiles.Contains(projectile.Id))
                        {
                            continue;
                        }

                        foreach (var enemyProjectile in enemyTeam.Projectiles)
                        {
                            //check projectile vs projectile
                            if (enemyProjectile.Bounds.Intersects(projectile.Bounds))
                            {
                                string collideLog = string.Format("{0}'s projectile ({1}) collided with {2}'s projectile ({3})", team.Name, projectile.Id, enemyTeam.Name, enemyProjectile.Id);
                                m_currentState.Events.Add(collideLog);

                                deadProjectiles.Add(enemyProjectile.Id);
                                deadProjectiles.Add(projectile.Id);


                                continue;
                            }
                        }

                        if (deadProjectiles.Contains(projectile.Id))
                        {
                            continue;
                        }
                    }

                    if (deadProjectiles.Contains(projectile.Id))
                    {
                        continue;
                    }
                }

                //Remove dead projectiles
                team.Projectiles = team.Projectiles.Where(p => !deadProjectiles.Contains(p.Id)).ToList();
            }

            //Check flag captures
            foreach (var team in masterTeams.Values)
            {
                //If the team's flag is captured...
                if (team.Flag.HeldBy != null)
                {
                    var holder = masterShips[team.Flag.HeldBy.Value];

                    team.Flag.Position = holder.Position;

                    var holderTeam = masterTeams[holder.Owner];
                    //If the flag's captor has brought the flag back to their team's base and their flag is there...
                    if (holderTeam.Flag.HeldBy == null && holderTeam.Flag.Bounds.Intersects(team.Flag.Bounds))
                    {
                        string capLog = string.Format("{0}'s flag has been captured by {1}'s ship ({2})", team.Name, holderTeam.Name, holder.Id);
                        m_currentState.Events.Add(capLog);

                        //Flag is captured!
                        holderTeam.FlagCaptures++;

                        //Reset flag
                        team.Flag.HeldBy   = null;
                        team.Flag.Position = SpawnPositions[team.Flag.Id];
                    }
                }
                else
                {
                    //If team's flag isn't captured...
                    foreach (var enemyTeam in masterTeams.Values)
                    {
                        if (enemyTeam.Id == team.Id)
                        {
                            continue;
                        }

                        //Check if any enemy ships are intersecting it
                        foreach (var ship in enemyTeam.Ships)
                        {
                            //Enemy pickup flag
                            if (ship.Bounds.Intersects(team.Flag.Bounds))
                            {
                                string pickupLog = string.Format("{0}'s flag has been taken by {1}'s ship ({2})", team.Name, enemyTeam.Name, ship.Id);
                                m_currentState.Events.Add(pickupLog);

                                team.Flag.HeldBy = ship.Id;
                                break;
                            }
                        }

                        if (team.Flag.HeldBy != null)
                        {
                            break;
                        }
                    }
                }
            }

            //AI Act
            foreach (var ai in m_ais)
            {
                var aiStateCopy = m_currentState.Clone();

                try
                {
                    //Pass game state to each AI
                    ai.Value.Update(aiStateCopy, aiStateCopy.Teams.First(t => t.Id == ai.Key), aiStateCopy.Teams.Where(t => t.Id != ai.Key).ToList());
                }
                catch
                {
                }

                updates[ai.Key] = aiStateCopy;
            }

            //Apply updates
            foreach (var update in updates)
            {
                var aiStateCopy = update.Value;
                var aiId        = update.Key;

                var team = aiStateCopy.Teams.FirstOrDefault(t => t.Id == aiId);
                if (team != null)
                {
                    if (team.Ships != null)
                    {
                        foreach (var updatedShip in team.Ships)
                        {
                            Ship masterShip = null;
                            if (masterShips.TryGetValue(updatedShip.Id, out masterShip))
                            {
                                if (masterShip.Owner == aiId)
                                {
                                    //Copy across updates from cloned state
                                    masterShip.SetLabel(updatedShip.Label);
                                    masterShip.SetThrust(updatedShip.Thrust);
                                    masterShip.SetTorque(updatedShip.Torque);
                                    if (updatedShip.IsFiring)
                                    {
                                        masterShip.Fire();
                                    }
                                    else
                                    {
                                        masterShip.StopFiring();
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //Step firing
            foreach (var ship in masterShips.Values)
            {
                if (ship.IsFiring)
                {
                    int lastFireTurn = m_lastFireTurns[ship.Id];

                    //Check the firing isn't on cooldown
                    if (m_currentState.TurnNumber - lastFireTurn > Rules.FireCooldown)
                    {
                        m_lastFireTurns[ship.Id] = m_currentState.TurnNumber;

                        var team = masterTeams[ship.Owner];

                        //Fire a projectile in the direction the ship is facing
                        team.Projectiles.Add(new Projectile()
                        {
                            Bounds   = new BoundingCircle(ship.Position, Rules.ProjectileRadius),
                            FiredBy  = ship.Id,
                            Owner    = team.Id,
                            Velocity = Vector2.FromPolar(Rules.ProjectileVelocity, ship.Rotation)
                        });
                    }
                }
            }

            //Step physics
            m_currentState = Step(m_currentState);
            States.Add(m_currentState);
        }
Esempio n. 5
0
        private CtfGameState Step(CtfGameState state)
        {
            CtfGameState newState = state.Clone();

            newState.TurnNumber++;

            foreach (var team in newState.Teams)
            {
                StepTeam(team);
            }

            return newState;
        }
Esempio n. 6
0
        /// <summary>
        /// Create a ctf game
        /// </summary>
        /// <param name="rules">The rules of this game</param>
        /// <param name="ais">All AIs that will be competing in this game</param>
        public CtfGame(CtfGameRules rules, IList<ICtfAi> ais)
        {
            if (rules == null)
            {
                throw new ArgumentNullException("rules");
            }

            if (ais == null)
            {
                throw new ArgumentNullException("ais");
            }

            SpawnPositions = new Dictionary<int, Vector2>();
            Rules = rules;
            States = new List<CtfGameState>(Rules.TurnLimit);

            //Calculate spacing of objects for spawn positions
            float teamSpacing = MathHelper.TwoPi / ais.Count;
            float shipSpacing = MathHelper.TwoPi / Rules.ShipsPerTeam;

            float flagRadius = Rules.ArenaRadius - (2 * Rules.ShipRadius) - Rules.FlagRadius;

            CtfGameState initialState = new CtfGameState();

            initialState.Teams = new List<Team>(ais.Count);
            int teamIndex = 0;

            //Initialise all the teams
            foreach (ICtfAi ai in ais)
            {
                var team = new Team()
                {
                    Name = ai.Name ?? "Unnamed AI"
                };

                team.Flag = new Flag()
                {
                    Bounds = new BoundingCircle(Vector2.FromPolar(flagRadius, teamSpacing * teamIndex), Rules.FlagRadius),
                    Owner = team.Id,
                };
                SpawnPositions[team.Flag.Id] = team.Flag.Position;

                m_ais[team.Id] = ai;

                team.Ships = new List<Ship>();

                for (int i = 0; i < rules.ShipsPerTeam; i++)
                {
                    var ship = new Ship()
                    {
                        Bounds = new BoundingCircle(team.Flag.Position + Vector2.FromPolar(Rules.FlagRadius + Rules.ShipRadius, i * shipSpacing), Rules.ShipRadius),
                        Owner = team.Id,
                        Rotation = (i * shipSpacing),
                    };

                    SpawnPositions[ship.Id] = ship.Position;
                    m_lastFireTurns[ship.Id] = int.MinValue + 1;

                    team.Ships.Add(ship);
                }

                team.Projectiles = new List<Projectile>();

                initialState.Teams.Add(team);

                teamIndex++;
            }

            States.Add(initialState);
            m_currentState = initialState;
        }
Esempio n. 7
0
        /// <summary>
        /// Advance the game by one turn
        /// </summary>
        public void Step()
        {
            if (IsGameOver)
            {
                return;
            }

            //Check for win condition
            if (States.Count == Rules.TurnLimit || m_currentState.Teams.Any(t => t.FlagCaptures == Rules.FlagLimit))
            {
                var winningTeam = m_currentState.Teams.OrderByDescending(t => t.FlagCaptures).ThenByDescending(t => t.Kills).FirstOrDefault();

                if (States.Count == Rules.TurnLimit)
                {
                    GameEndReason = "Turn limit reached";
                }
                else if (m_currentState.Teams.Any(t => t.FlagCaptures == Rules.FlagLimit))
                {
                    GameEndReason = string.Format("AI {0} ({1}) reached the flag capture limit", winningTeam.Name, winningTeam.Id);
                }

                m_currentState.Events.Add(GameEndReason);

                WinningTeam = winningTeam.Id;

                return;
            }

            IDictionary<int, Ship> masterShips = m_currentState.Teams.SelectMany(t => t.Ships).ToDictionary(s => s.Id);
            IDictionary<int, Team> masterTeams = m_currentState.Teams.ToDictionary(t => t.Id);
            IDictionary<int, CtfGameState> updates = new Dictionary<int, CtfGameState>();
            HashSet<int> deadProjectiles = new HashSet<int>();

            //Resolve collisions
            foreach (var team in masterTeams.Values)
            {
                foreach (var projectile in team.Projectiles)
                {
                    if (deadProjectiles.Contains(projectile.Id))
                    {
                        //Check if this projectile was previously hit by another projectile
                        continue;
                    }

                    //Remove projectiles that go out of bounts
                    if (projectile.Position.Length() > Rules.ArenaRadius)
                    {
                        deadProjectiles.Add(projectile.Id);
                        continue;
                    }

                    foreach (var enemyTeam in masterTeams.Values)
                    {
                        if (team.Id == enemyTeam.Id)
                        {
                            continue;
                        }

                        foreach (var enemyShip in enemyTeam.Ships)
                        {
                            if (enemyShip.Bounds.Intersects(projectile.Bounds))
                            {
                                string killLog = string.Format("{0}'s ship ({1}) was killed by {2}'s ship ({3})", enemyTeam.Name, enemyShip.Id, team.Name, masterShips[projectile.FiredBy].Id);
                                m_currentState.Events.Add(killLog);

                                //Ship hit
                                deadProjectiles.Add(projectile.Id);
                                enemyShip.Position = SpawnPositions[enemyShip.Id];
                                team.Kills++;

                                //Reset flag position if the killed ship was holding a flag
                                foreach (var t in masterTeams.Values)
                                {
                                    if (t.Flag.HeldBy == enemyShip.Id)
                                    {
                                        string dropLog = string.Format("{0}'s flag was dropped by {1}'s ship ({2}) after it was killed", masterTeams[t.Flag.Owner].Name, enemyTeam.Name, enemyShip.Id);
                                        m_currentState.Events.Add(dropLog);
                                        t.Flag.HeldBy = null;
                                        t.Flag.Position = SpawnPositions[team.Flag.Id];
                                    }
                                }

                                continue;
                            }
                        }

                        if (deadProjectiles.Contains(projectile.Id))
                        {
                            continue;
                        }

                        foreach (var enemyProjectile in enemyTeam.Projectiles)
                        {
                            //check projectile vs projectile
                            if (enemyProjectile.Bounds.Intersects(projectile.Bounds))
                            {
                                string collideLog = string.Format("{0}'s projectile ({1}) collided with {2}'s projectile ({3})", team.Name, projectile.Id, enemyTeam.Name, enemyProjectile.Id);
                                m_currentState.Events.Add(collideLog);

                                deadProjectiles.Add(enemyProjectile.Id);
                                deadProjectiles.Add(projectile.Id);

                                continue;
                            }
                        }

                        if (deadProjectiles.Contains(projectile.Id))
                        {
                            continue;
                        }
                    }

                    if (deadProjectiles.Contains(projectile.Id))
                    {
                        continue;
                    }
                }

                //Remove dead projectiles
                team.Projectiles = team.Projectiles.Where(p => !deadProjectiles.Contains(p.Id)).ToList();
            }

            //Check flag captures
            foreach (var team in masterTeams.Values)
            {
                //If the team's flag is captured...
                if (team.Flag.HeldBy != null)
                {
                    var holder = masterShips[team.Flag.HeldBy.Value];

                    team.Flag.Position = holder.Position;

                    var holderTeam = masterTeams[holder.Owner];
                    //If the flag's captor has brought the flag back to their team's base and their flag is there...
                    if (holderTeam.Flag.HeldBy == null && holderTeam.Flag.Bounds.Intersects(team.Flag.Bounds))
                    {
                        string capLog = string.Format("{0}'s flag has been captured by {1}'s ship ({2})", team.Name, holderTeam.Name, holder.Id);
                        m_currentState.Events.Add(capLog);

                        //Flag is captured!
                        holderTeam.FlagCaptures++;

                        //Reset flag
                        team.Flag.HeldBy = null;
                        team.Flag.Position = SpawnPositions[team.Flag.Id];
                    }
                }
                else
                {
                    //If team's flag isn't captured...
                    foreach (var enemyTeam in masterTeams.Values)
                    {
                        if (enemyTeam.Id == team.Id)
                        {
                            continue;
                        }

                        //Check if any enemy ships are intersecting it
                        foreach (var ship in enemyTeam.Ships)
                        {
                            //Enemy pickup flag
                            if (ship.Bounds.Intersects(team.Flag.Bounds))
                            {
                                string pickupLog = string.Format("{0}'s flag has been taken by {1}'s ship ({2})", team.Name, enemyTeam.Name, ship.Id);
                                m_currentState.Events.Add(pickupLog);

                                team.Flag.HeldBy = ship.Id;
                                break;
                            }
                        }

                        if (team.Flag.HeldBy != null)
                        {
                            break;
                        }
                    }
                }
            }

            //AI Act
            foreach (var ai in m_ais)
            {
                var aiStateCopy = m_currentState.Clone();

                try
                {
                    //Pass game state to each AI
                    ai.Value.Update(aiStateCopy, aiStateCopy.Teams.First(t => t.Id == ai.Key), aiStateCopy.Teams.Where(t => t.Id != ai.Key).ToList());
                }
                catch
                {
                }

                updates[ai.Key] = aiStateCopy;
            }

            //Apply updates
            foreach (var update in updates)
            {
                var aiStateCopy = update.Value;
                var aiId = update.Key;

                var team = aiStateCopy.Teams.FirstOrDefault(t => t.Id == aiId);
                if (team != null)
                {
                    if (team.Ships != null)
                    {
                        foreach (var updatedShip in team.Ships)
                        {
                            Ship masterShip = null;
                            if (masterShips.TryGetValue(updatedShip.Id, out masterShip))
                            {
                                if (masterShip.Owner == aiId)
                                {
                                    //Copy across updates from cloned state
                                    masterShip.SetLabel(updatedShip.Label);
                                    masterShip.SetThrust(updatedShip.Thrust);
                                    masterShip.SetTorque(updatedShip.Torque);
                                    if (updatedShip.IsFiring)
                                    {
                                        masterShip.Fire();
                                    }
                                    else
                                    {
                                        masterShip.StopFiring();
                                    }
                                }
                            }
                        }
                    }
                }
            }

            //Step firing
            foreach (var ship in masterShips.Values)
            {
                if (ship.IsFiring)
                {
                    int lastFireTurn = m_lastFireTurns[ship.Id];

                    //Check the firing isn't on cooldown
                    if (m_currentState.TurnNumber - lastFireTurn > Rules.FireCooldown)
                    {
                        m_lastFireTurns[ship.Id] = m_currentState.TurnNumber;

                        var team = masterTeams[ship.Owner];

                        //Fire a projectile in the direction the ship is facing
                        team.Projectiles.Add(new Projectile()
                        {
                            Bounds = new BoundingCircle(ship.Position, Rules.ProjectileRadius),
                            FiredBy = ship.Id,
                            Owner = team.Id,
                            Velocity = Vector2.FromPolar(Rules.ProjectileVelocity, ship.Rotation)
                        });
                    }
                }
            }

            //Step physics
            m_currentState = Step(m_currentState);
            States.Add(m_currentState);
        }