private void ApplyRobotAction(LambdaRobot robot, LambdaRobotAction action) { // reduce reload time if any is active if (robot.ReloadCoolDown > 0) { robot.ReloadCoolDown = Math.Max(0.0, robot.ReloadCoolDown - Game.SecondsPerTurn); } // check if any actions need to be applied if (action == null) { // robot didn't respond with an action; consider it dead robot.Status = LambdaRobotStatus.Dead; robot.TimeOfDeathGameTurn = Game.TotalTurns; AddMessage($"{robot.Name} (R{robot.Index}) was disqualified by lack of action"); return; } // update speed and heading robot.TargetSpeed = MinMax(0.0, action.Speed ?? robot.TargetSpeed, robot.MaxSpeed); robot.TargetHeading = NormalizeAngle(action.Heading ?? robot.TargetHeading); // fire missile if requested and possible if ((action.FireMissileHeading.HasValue || action.FireMissileDistance.HasValue) && (robot.ReloadCoolDown == 0.0)) { // update robot state ++robot.TotalMissileFiredCount; robot.ReloadCoolDown = robot.MissileReloadCooldown; // add missile var missile = new LambdaRobotMissile { Id = $"{robot.Id}:M{robot.TotalMissileFiredCount}", RobotId = robot.Id, Status = MissileStatus.Flying, X = robot.X, Y = robot.Y, Speed = robot.MissileVelocity, Heading = NormalizeAngle(action.FireMissileHeading ?? robot.Heading), Range = MinMax(0.0, action.FireMissileDistance ?? robot.MissileRange, robot.MissileRange), DirectHitDamageBonus = robot.MissileDirectHitDamageBonus, NearHitDamageBonus = robot.MissileNearHitDamageBonus, FarHitDamageBonus = robot.MissileFarHitDamageBonus }; Game.Missiles.Add(missile); } }
private void MoveMissile(LambdaRobotMissile missile) { bool collision; Move( missile.X, missile.Y, missile.Distance, missile.Speed, missile.Heading, missile.Range, out missile.X, out missile.Y, out missile.Distance, out collision ); if (collision) { missile.Status = MissileStatus.ExplodingDirect; missile.Speed = 0.0; } }
private void AssessMissileDamage(LambdaRobotMissile missile) { FindRobotsByDistance(missile.X, missile.Y, (robot, distance) => { // compute damage dealt by missile double damage = 0.0; string damageType = null; switch (missile.Status) { case MissileStatus.ExplodingDirect: if (distance <= Game.DirectHitRange) { damage = robot.DirectHitDamage + missile.DirectHitDamageBonus; damageType = "direct"; } break; case MissileStatus.ExplodingNear: if (distance <= Game.NearHitRange) { damage = robot.NearHitDamage + missile.NearHitDamageBonus; damageType = "near"; } break; case MissileStatus.ExplodingFar: if (distance <= Game.FarHitRange) { damage = robot.FarHitDamage + missile.FarHitDamageBonus; damageType = "far"; } break; } // check if any damage was dealt if (damage == 0.0) { // stop enumerating more robots since they will be further away return(false); } // record damage dealt var from = Game.Robots.FirstOrDefault(fromRobot => fromRobot.Id == missile.RobotId); if (from != null) { from.TotalDamageDealt += damage; ++from.TotalMissileHitCount; // check if robot was killed if (Damage(robot, damage)) { ++from.TotalKills; // check if robot inflicted damage to itself if (robot.Id == from.Id) { AddMessage($"{robot.Name} (R{robot.Index}) killed itself"); } else { AddMessage($"{robot.Name} (R{robot.Index}) was killed by {from.Name}"); } } else { // check if robot inflicted damage to itself if (robot.Id == from.Id) { AddMessage($"{robot.Name} (R{robot.Index}) caused {damage:N0} {damageType} damage to itself"); } else { AddMessage($"{robot.Name} (R{robot.Index}) received {damage:N0} {damageType} damage from {from.Name} (R{from.Index})"); } } } return(true); }); }