Esempio n. 1
0
        private CtfGameState Step(CtfGameState state)
        {
            CtfGameState newState = state.Clone();

            newState.TurnNumber++;

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

            return(newState);
        }
Esempio n. 2
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. 3
0
        private CtfGameState Step(CtfGameState state)
        {
            CtfGameState newState = state.Clone();

            newState.TurnNumber++;

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

            return newState;
        }