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); } }
public override sealed async Task <LambdaRobotResponse> ProcessMessageAsync(LambdaRobotRequest request) { // NOTE (2019-10-03, bjorg): this method dispatches to other methods based on the incoming // request; most likely, there is nothing to change here. LogInfo($"Request:\n{SerializeJson(request)}"); // check if there is a state object to load var robotStateRecord = await _table.GetAsync <LambdaRobotStateRecord>(request.Robot.Id); if (robotStateRecord == null) { robotStateRecord = new LambdaRobotStateRecord { PK = request.Robot.Id, State = new TState(), Expire = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds() }; } State = robotStateRecord.State; LogInfo($"Starting State:\n{SerializeJson(State)}"); // dispatch to specific method based on request command LambdaRobotResponse response; switch (request.Command) { case LambdaRobotCommand.GetBuild: // robot configuration request response = new LambdaRobotResponse { RobotBuild = await GetBuildAsync() }; break; case LambdaRobotCommand.GetAction: // robot action request try { // capture request fields for easy access Game = request.Game; Robot = request.Robot; // initialize a default empty action _action = new LambdaRobotAction(); // get robot action await GetActionAsync(); // generate response response = new LambdaRobotResponse { RobotAction = _action }; } finally { Robot = null; } break; default: // unrecognized request throw new ApplicationException($"unexpected request: '{request.Command}'"); } // check if there is a state object to save robotStateRecord.Expire = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds(); await _table.CreateOrUpdateAsync(robotStateRecord); // log response and return LogInfo($"Final State:\n{SerializeJson(State)}"); LogInfo($"Response:\n{SerializeJson(response)}"); return(response); }