Example #1
0
 private bool Damage(LambdaRobot robot, double damage)
 {
     robot.Damage += damage;
     if (robot.Damage >= robot.MaxDamage)
     {
         robot.Damage = robot.MaxDamage;
         robot.Status = LambdaRobotStatus.Dead;
         robot.TimeOfDeathGameTurn = Game.TotalTurns;
         return(true);
     }
     return(false);
 }
Example #2
0
        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);
            }
        }
Example #3
0
        private async Task <LambdaRobotAction> GetRobotActionAsync(Game game, LambdaRobot robot, string lambdaArn)
        {
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();

            try {
                var getActionTask = _lambdaClient.InvokeAsync(new InvokeRequest {
                    Payload = SerializeJson(new LambdaRobotRequest {
                        Command = LambdaRobotCommand.GetAction,
                        Game    = new GameInfo {
                            Id             = game.Id,
                            BoardWidth     = game.BoardWidth,
                            BoardHeight    = game.BoardHeight,
                            DirectHitRange = game.DirectHitRange,
                            NearHitRange   = game.NearHitRange,
                            FarHitRange    = game.FarHitRange,
                            CollisionRange = game.CollisionRange,
                            GameTurn       = game.TotalTurns,
                            MaxGameTurns   = game.MaxTurns,
                            MaxBuildPoints = game.MaxBuildPoints,
                            SecondsPerTurn = game.SecondsPerTurn,
                            ApiUrl         = _gameApiUrl
                        },
                        Robot = robot
                    }),
                    FunctionName   = lambdaArn,
                    InvocationType = InvocationType.RequestResponse
                });

                // check if lambda responds within time limit
                if (await Task.WhenAny(getActionTask, Task.Delay(TimeSpan.FromSeconds(game.RobotTimeoutSeconds))) != getActionTask)
                {
                    LogInfo($"Robot {robot.Id} GetAction timed out after {stopwatch.Elapsed.TotalSeconds:N2}s");
                    return(null);
                }
                var response = Encoding.UTF8.GetString(getActionTask.Result.Payload.ToArray());
                var result   = DeserializeJson <LambdaRobotResponse>(response);
                LogInfo($"Robot {robot.Id} GetAction responded in {stopwatch.Elapsed.TotalSeconds:N2}s:\n{response}");
                return(result.RobotAction);
            } catch (Exception e) {
                LogErrorAsWarning(e, $"Robot {robot.Id} GetAction failed (arn: {lambdaArn})");
                return(null);
            }
        }
Example #4
0
        public LambdaRobot ScanRobots(LambdaRobot robot, double heading, double resolution)
        {
            LambdaRobot result = null;

            resolution = MinMax(0.01, resolution, robot.RadarMaxResolution);
            FindRobotsByDistance(robot.X, robot.Y, (other, distance) => {
                // skip ourselves
                if (other.Id == robot.Id)
                {
                    return(true);
                }

                // compute relative position
                var deltaX = other.X - robot.X;
                var deltaY = other.Y - robot.Y;

                // check if other robot is beyond scan range
                if (distance > robot.RadarRange)
                {
                    // no need to enumerate more
                    return(false);
                }

                // check if delta angle is within resolution limit
                var angle = Math.Atan2(deltaX, deltaY) * 180.0 / Math.PI;
                if (Math.Abs(NormalizeAngle(heading - angle)) <= resolution)
                {
                    // found a robot within range and resolution; stop enumerating
                    result = other;
                    return(false);
                }

                // enumerate more
                return(true);
            });
            return(result);
        }
Example #5
0
 public Task <LambdaRobotAction> GetRobotAction(LambdaRobot robot) => _getAction(robot);
Example #6
0
 public Task <LambdaRobotBuild> GetRobotBuild(LambdaRobot robot) => _getBuild(robot);
Example #7
0
        private void MoveRobot(LambdaRobot robot)
        {
            // compute new heading
            if (robot.Heading != robot.TargetHeading)
            {
                if (robot.Speed <= robot.MaxTurnSpeed)
                {
                    robot.Heading = robot.TargetHeading;
                }
                else
                {
                    robot.TargetSpeed = 0;
                    robot.Heading     = robot.TargetHeading;
                    AddMessage($"{robot.Name} (R{robot.Index}) stopped by sudden turn");
                }
            }

            // compute new speed
            var oldSpeed = robot.Speed;

            if (robot.TargetSpeed > robot.Speed)
            {
                robot.Speed = Math.Min(robot.TargetSpeed, robot.Speed + robot.Acceleration * Game.SecondsPerTurn);
            }
            else if (robot.TargetSpeed < robot.Speed)
            {
                robot.Speed = Math.Max(robot.TargetSpeed, robot.Speed - robot.Deceleration * Game.SecondsPerTurn);
            }
            var effectiveSpeed = (robot.Speed + oldSpeed) / 2.0;

            // move robot
            bool collision;

            Move(
                robot.X,
                robot.Y,
                robot.TotalTravelDistance,
                effectiveSpeed,
                robot.Heading,
                double.MaxValue,
                out robot.X,
                out robot.Y,
                out robot.TotalTravelDistance,
                out collision
                );

            // check for collision with wall
            if (collision)
            {
                robot.Speed       = 0.0;
                robot.TargetSpeed = 0.0;
                ++robot.TotalCollisions;
                if (Damage(robot, robot.CollisionDamage))
                {
                    AddMessage($"{robot.Name} (R{robot.Index}) was destroyed by wall collision");
                    return;
                }
                else
                {
                    AddMessage($"{robot.Name} (R{robot.Index}) received {robot.CollisionDamage:N0} damage by wall collision");
                }
            }

            // check if robot collides with any other robot
            FindRobotsByDistance(robot.X, robot.Y, (other, distance) => {
                if ((other.Id != robot.Id) && (distance < Game.CollisionRange))
                {
                    robot.Speed       = 0.0;
                    robot.TargetSpeed = 0.0;
                    ++robot.TotalCollisions;
                    if (Damage(robot, robot.CollisionDamage))
                    {
                        AddMessage($"{robot.Name} (R{robot.Index}) was destroyed by collision with {other.Name}");
                    }
                    else
                    {
                        AddMessage($"{robot.Name} (R{robot.Index}) was damaged {robot.CollisionDamage:N0} by collision with {other.Name} (R{other.Index})");
                    }
                }

                // keep looking for more collisions unless robot is dead or nearest robot is out of range
                return((robot.Status == LambdaRobotStatus.Alive) && (distance < Game.CollisionRange));
            });
        }