/// <summary> /// Fires at target. /// </summary> /// <param name="location">The current location.</param> /// <param name="target">The closest target.</param> /// <param name="direction">The direction.</param> private void FireAtTarget(Point location, EnemyData target) { var absBearing = target.BearingRadians + this.HeadingRadians; int direction = (Math.Sin(target.HeadingRadians - absBearing) * target.Velocity < 0) ? -1 : 1; var distance = Point.Distance(location, target.Location); double power = GetFirePower(distance); var fieldArea = GetFieldArea(target.Location); var distanceBucket = (int)(distance / 100); var lastBullet = target.LastBullet; // initialize it to be in the middle, guessfactor 0. int bestindex = guessFactors / 2; var stats = this.statistics.GetStatistics(target.Name); var bestStats = stats.SegmentedTargeting.Where(x => x.DistanceBucket == distanceBucket && x.FieldAreaBucket == fieldArea).OrderByDescending(x => x.Value).FirstOrDefault(); if (bestStats != null) { bestindex = bestStats.GuessFactorBucket; } // this should do the opposite of the math in the WaveBullet double guessfactor = (double)(bestindex - (guessFactors - 1) / 2) / ((guessFactors - 1) / 2); double angleOffset = direction * guessfactor * lastBullet.MaxEscapeAngle(); double gunAdjust = Utils.NormalRelativeAngle(lastBullet.StartBearing - this.GunHeadingRadians + angleOffset); this.SetTurnGunRightRadians(gunAdjust); if (this.GunHeat == 0 && gunAdjust < Math.Atan2(9, distance)) { this.SetFireBullet(power); } }
/// <summary> /// Gets the move target using radius sampling method /// </summary> /// <param name="location">The current location.</param> /// <param name="closestTarget">The closest target.</param> /// <param name="enemyLocations">Enemy locations.</param> /// <param name="angleChange">if set to <c>true</c>, a significant change of move angle has occured.</param> /// <returns></returns> private double GetRadiusSamplingMoveTarget(Point location, EnemyData closestTarget, List<Point> enemyLocations, out bool angleChange) { var potentialMoveTargets = GetPotentialMoveTargets(this.moveTargetSampleSize, location, enemyLocations, this.defaultDistance, this.maximumDistance, this.BattleFieldWidth, this.BattleFieldHeight); // move towards the closest target var moveTarget = potentialMoveTargets.OrderByDescending(x => Point.Distance(x, closestTarget.Location)).First(); var angle = Math.Atan2(moveTarget.X - location.X, moveTarget.Y - location.Y); // not important if using this move method angleChange = false; return angle; }
/// <summary> /// Handle the scan event. /// /// Predict whether the enemy has fired. /// Fire a wave bullet atth /// </summary> /// <param name="evnt"></param> /// <inheritdoc/> public override void OnScannedRobot(ScannedRobotEvent evnt) { var name = evnt.Name; var absBearing = evnt.BearingRadians + this.HeadingRadians; int direction = (Math.Sin(evnt.HeadingRadians - absBearing) * evnt.Velocity < 0) ? -1 : 1; // if fighting one-on-one, maintain radar lock if (this.GunHeat < 1.0 && this.Others == 1) { var turn = this.HeadingRadians + evnt.BearingRadians - this.RadarHeadingRadians; this.SetTurnRadarRightRadians(this.radarFactor * Utils.NormalRelativeAngle(turn)); } // get the updated enemy data snapshot var enemyData = new EnemyData() { Name = name, Location = new Point() { X = this.X + Math.Sin(absBearing) * evnt.Distance, Y = this.Y + Math.Cos(absBearing) * evnt.Distance }, Time = evnt.Time, Energy = evnt.Energy, HeadingRadians = evnt.HeadingRadians, BearingRadians = evnt.BearingRadians, Velocity = evnt.Velocity }; // predict whether the enemy has fired a bullet since last scan // skip this step if there are many robots left on the field to avoid noise if (this.Others <= 2) { if (enemies.ContainsKey(name)) { var energyDrop = enemies[name].Energy - enemyData.Energy; if (energyDrop >= 0.1 && energyDrop <= 3) { this.enemyBullets.Add(new WaveBullet() { TargetName = this.Name, StartPoint = enemyData.Location, StartBearing = Utils.NormalRelativeAngle(Math.PI - absBearing), Power = energyDrop, Direction = direction, Time = this.Time }); } } } // update the enemy data this.enemies[name] = enemyData; // process targeting statistics var targetStatistics = this.statistics.GetStatistics(name); // add the enemy data to pattern history for pattern matching targeting //targetStatistics.PatternHistory.Add(enemyData); // fire a wave bullet at the enemy double power = GetFirePower(evnt.Distance); var location = new Point() { X = this.X, Y = this.Y }; var waveBullet = new WaveBullet() { TargetName = name, StartPoint = location, StartBearing = absBearing, Power = power, Direction = direction, Time = this.Time }; enemyData.LastBullet = waveBullet; targetStatistics.WaveBullets.Add(waveBullet); }