/// <summary> /// Called from the Arena, when a bot calls the Arena.Cannon() method /// /// The Cannon() function fires a missile heading a specified range and direction. /// Cannon() returns 1 (true) if a missile was fired, or 0 (false) if the cannon is reloading. /// Degree is forced into the range 0-359 as in Scan() and Drive(). /// Range can be 0-700, with greater ranges truncated to 700. /// /// Examples: /// degree = 45; // set a direction to test /// if ((range=Scan(robot, degree, 2)) > 0) // see if a target is there /// Cannon(robot, degree, range); // fire a missile /// </summary> /// <param name="robot"></param> /// <param name="degree"></param> /// <param name="range"></param> /// <returns></returns> public bool FireCannon(Robot robot, int degree, int range) { degree = Arena.DegreeTo360(degree); if (range < 0) { range = 0; } if (range > 700) { range = 700; } BotAssembly bot = Bots.Find(botAssembly => botAssembly.Id == robot.Id); if (bot.MissilesInFlight < MaxMissles) { bot.MissilesInFlight++; Missiles.Add(new Missile { Id = robot.Id, Speed = 100, Location = new PointF { X = bot.Location.X, Y = bot.Location.Y }, Direction = degree, Range = range }); return(true); } return(false); }
/// <summary> /// Called from the Arena, when a bot calls the Arena.Scan() method /// /// The Scan() function invokes the robot's scanner, at a specified degree and resolution. /// Scan() returns 0 if no robots are within the scan range or a positive integer representing /// the range to the closest robot. Degree should be within the range 0-359, otherwise degree /// is forced into 0-359 by a modulo 360 operation, and made positive if necessary. /// Resolution controls the scanner's sensing resolution, up to +/- 10 degrees. /// /// Examples: /// range = Scan(robot, 45, 0); // scan 45, with no variance /// range = Scan(robot, 365, 10); // scans the range from 355 to 15 /// </summary> /// <param name="robot"></param> /// <param name="degree"></param> /// <param name="resolution"></param> /// <returns></returns> public int Scan(Robot robot, int degree, int resolution) { degree = Arena.DegreeTo360(degree); if (resolution < 0) { resolution = 0; } if (resolution > MaxScanResolution) { resolution = MaxScanResolution; } // Get the BotAssembly of the given robot from our list of robots BotAssembly botAssembly = Bots.Find(ba => ba.Id == robot.Id); // Update these for display botAssembly.ScanDirection = degree; botAssembly.ScanResolution = resolution; // Iterate all bots (Max of 4 bots in the game) foreach (var bot in Bots) { // As long as it is not the given robot if (bot != botAssembly) { // Plot a course from this bot to the given methods bot int course = Arena.PlotCourse((int)bot.Location.X, (int)bot.Location.Y, (int)botAssembly.Location.X, (int)botAssembly.Location.Y); // Given the Scan resolution ( +/- 10 degrees maximum ) is there a bot out there? int degStart = Arena.DegreeTo360(degree - resolution); int degEnd = Arena.DegreeTo360(degree + resolution); for (int scanResolution = degStart; scanResolution <= degEnd; ++scanResolution) { if (course == scanResolution) { // Return the range to the discovered target int range = Math.Abs(Arena.Distance((int)bot.Location.X, (int)bot.Location.Y, (int)botAssembly.Location.X, (int)botAssembly.Location.Y)); // Return the range to the discovered robot if distance is MaxScanRange or less return(range);//range >= MaxScanRange ? range : 0; } } } } // No robot found return(0); }
public void Process() { if (!_chips[0].HasValue || !_chips[1].HasValue) { return; } //One Star if (_chips.Contains(61) && _chips.Contains(17)) { Console.WriteLine("*: Bot " + Id); } int high; int low; if (_chips[0] > _chips[1]) { high = _chips[0].Value; low = _chips[1].Value; } else { high = _chips[1].Value; low = _chips[0].Value; } _chips[0] = null; _chips[1] = null; if (HighOutput) { Outputs[High] = high; } else { var highBot = Bots.Find(b => b.Id == High); highBot.GiveChip(high); highBot.Process(); } if (LowOutput) { Outputs[Low] = low; } else { var lowBot = Bots.Find(b => b.Id == Low); lowBot.GiveChip(low); lowBot.Process(); } }
/// <summary> /// The Execute method is called repeatedly and runs the robots /// on the battle field calling each robots Execute method, updating /// in flight missiles, checking for collisions and updating damage. /// </summary> public bool Execute() { int totalDamage = 0; // Work out how long since we were last here in seconds double gameTime = _timer.ElapsedMilliseconds / 1000.0; double elapsedTime = gameTime - _lastTime; _lastTime = gameTime; // Remove any missiles that died last game frame if (_deadMissiles) { RemoveDeadMissles(); } // Update any missiles foreach (var missile in Missiles) { missile.LastLocation = missile.Location; // Update robot position based on the velocity missile.Location.X += (float)Math.Sin(missile.Direction * Math.PI / 180) * missile.Speed * (float)elapsedTime; missile.Location.Y += (float)Math.Cos(missile.Direction * Math.PI / 180) * missile.Speed * (float)elapsedTime; missile.Range -= Arena.Distance((int)missile.LastLocation.X, (int)missile.LastLocation.Y, (int)missile.Location.X, (int)missile.Location.Y); // If a missile is leaving the arena, i.e. hitting a wall, explode it by setting it's range to 0 if (missile.Location.X < 0 || missile.Location.Y < 0 || missile.Location.X > ArenaWidth - 1 || missile.Location.Y > ArenaHeight - 1) { missile.Range = 0; } // Missile has reached it's defined range. if (missile.Range <= 0) { // Explode the missile // TODO Determine any damage to bots in the area // Iterate each robot. Get range to this missile. If in damage range, apply the damage. // Update the bot that fired the missile Missile missile1 = missile; BotAssembly bot = Bots.Find(botAssembly => botAssembly.Id == missile1.Id); bot.MissilesInFlight--; // Mark missile as dead so we can clean it up missile.Dead = true; _deadMissiles = true; } } // Update bots foreach (var bot in Bots) { totalDamage += bot.Damage; // 100% damaged bots do nothing if (bot.Damage != 100) { // Check if robot is changing there speed // TODO Need to ramp up/down to the robots set speed //if (bot.Speed != bot.LastSpeed) //{ // if (bot.Direction >= 0 && bot.Direction <= 180) // { // bot.Velocity.X += 40; // bot.Velocity.Y += 40; // } // else // { // bot.Velocity.X -= 40; // bot.Velocity.Y -= 40; // } // bot.LastSpeed = bot.Speed; //} bot.LastLocation = bot.Location; // Update robot position based on the velocity bot.Location.X += (float)Math.Sin(bot.Direction * Math.PI / 180) * bot.Speed * (float)elapsedTime; bot.Location.Y += (float)Math.Cos(bot.Direction * Math.PI / 180) * bot.Speed * (float)elapsedTime; // Fix the robots position to not leave the Arena if (bot.Location.X < 0) { bot.Location.X = 0; } if (bot.Location.X > ArenaWidth - 1) { bot.Location.X = ArenaWidth - 1; } if (bot.Location.Y < 0) { bot.Location.Y = 0; } if (bot.Location.Y > ArenaHeight - 1) { bot.Location.Y = ArenaHeight - 1; } // TODO Add collision detection and damage // Have robots perform an execution step bot.Assembly.GetType(Namespace + "." + bot.ClassName).GetMethod(ExecuteMethod).Invoke(bot.AssemblyInstance, null); } } return(totalDamage == 300 ? false : true); }