public static void CaptureBefore(Player player, List <Element> elements, float angleToCenter, bool inZone) { var data = GetData(player); // capture the angle to the center data.CenterAngle = angleToCenter; // capture the user health, shield, weapon status, inzone, Z data.Angle = player.Angle; data.Health = player.Health; data.InZone = inZone; data.Primary = player.Primary != null?player.Primary.GetType().Name : ""; data.PrimaryAmmo = player.Primary != null ? player.Primary.Ammo : 0; data.PrimaryClip = player.Primary != null ? player.Primary.Clip : 0; data.Secondary = player.Secondary != null?player.Secondary.GetType().Name : ""; data.SecondaryAmmo = player.Secondary != null ? player.Secondary.Ammo : 0; data.SecondaryClip = player.Secondary != null ? player.Secondary.Clip : 0; data.Shield = player.Shield; data.Z = player.Z; // capture what the user sees data.Proximity = AITraining.ComputeProximity(player, elements).Values.ToList(); }
public static void CaptureBefore(Player player, ActionDetails details) { var data = GetData(player); lock (data) { // capture the angle to the center data.CenterAngle = details.AngleToCenter; // capture the user health, shield, weapon status, inzone, Z data.Angle = player.Angle; data.Health = player.Health; data.InZone = details.InZone; data.Xdelta = details.XDelta; data.Ydelta = details.YDelta; if (player.Primary != null && player.Primary is RangeWeapon) { data.Primary = player.Primary.GetType().Name; data.PrimaryAmmo = (player.Primary as RangeWeapon).Ammo; data.PrimaryClip = (player.Primary as RangeWeapon).Clip; } else { data.Primary = ""; data.PrimaryAmmo = data.PrimaryClip = 0; } if (player.Secondary != null && player.Secondary.Length == 1 && player.Secondary[0] != null && player.Secondary[0] is RangeWeapon) { data.Secondary = player.Secondary.GetType().Name; data.SecondaryAmmo = (player.Secondary[0] as RangeWeapon).Ammo; data.SecondaryClip = (player.Secondary[0] as RangeWeapon).Clip; } else { data.Secondary = ""; data.SecondaryAmmo = data.SecondaryClip = 0; } data.Shield = player.Shield; data.Z = player.Z; // capture what the user sees data.Proximity = AITraining.ComputeProximity(player, details.Elements).Values.ToList(); } }
public override ActionEnum Action(List <Element> elements, float angleToCenter, bool inZone, ref float xdelta, ref float ydelta, ref float zdelta, ref float angle) { var playerCount = 0; float playerX = 0; float playerY = 0; bool shouldMelee = false; // find proximity to all types var closest = AITraining.ComputeProximity(this, elements); // gather details about if there is a crowd foreach (var elem in elements) { if (elem.Id == Id) { continue; // found myself } if (!(elem is Player)) { continue; // only care about players } playerCount++; playerX += elem.X; playerY += elem.Y; } // calculate the average center (if there are players near by) if (playerCount >= 1) { playerX /= (float)playerCount; playerY /= (float)playerCount; } // choose an action - set the rules in reverse order in order to set precedence var action = ActionEnum.None; xdelta = ydelta = angle = 0; if (PreviousAngle < 0) { // choose an angle at random PreviousAngle = Rand.Next() % 360; } angle = PreviousAngle; // 3) Shield if (Shield < Constants.MaxShield) { ElementProximity helmet = null; if (closest.TryGetValue(typeof(Shield), out helmet)) { // there is health either close or touching if (IsTouching(helmet, Width / 2)) { // choose to pickup action = ActionEnum.Pickup; // set direction via another decision PreviousPickupId = helmet.Id; } else { // choose action via another decision angle = helmet.Angle; } } } // 2) Health if (Health < Constants.MaxHealth) { ElementProximity bandage = null; if (closest.TryGetValue(typeof(Health), out bandage)) { // there is health either close or touching if (IsTouching(bandage, Width / 2)) { // choose to pickup action = ActionEnum.Pickup; // set direction via another decision PreviousPickupId = bandage.Id; } else { // choose action via another decision angle = bandage.Angle; } } } // 1) Have weapon if (Primary != null && Primary is RangeWeapon) { var weapon = Primary as RangeWeapon; ElementProximity ammo = null; // need ammo if (weapon.Ammo < MinAmmo && closest.TryGetValue(typeof(Ammo), out ammo)) { // there is ammo either close or touching if (IsTouching(ammo, Width / 2)) { // choose to pickup action = ActionEnum.Pickup; // set direction via another decision PreviousPickupId = ammo.Id; } else { // choose action via another decision angle = ammo.Angle; } } // needs reload if (!weapon.RoundsInClip(out int rounds) && rounds == 0 && weapon.HasAmmo()) { // choose to reload action = ActionEnum.Reload; // choose direction via another decision } ElementProximity ak47 = null; // pick up ak47 if (!(Primary is AK47) && closest.TryGetValue(typeof(AK47), out ak47)) { // there is an AK47 either close or touching if (IsTouching(ak47, Width / 2)) { // choose to pickup action = ActionEnum.Pickup; // set direction via another decision PreviousPickupId = ak47.Id; } else { // choose action via another decision angle = ak47.Angle; } } ElementProximity player = null; // shoot a player if (weapon.CanShoot() && closest.TryGetValue(typeof(Player), out player)) { // choose to shoot action = ActionEnum.Attack; // move towards the player angle = player.Angle; } } // 0) No weapon if (Primary == null || !(Primary is RangeWeapon)) { // AI does not have a weapon, so go ahead and melee (if no other action) shouldMelee = true; // 0.b if near a player, melee ElementProximity player = null; if (closest.TryGetValue(typeof(Player), out player)) { if (IsTouching(player, Fists.Distance)) { // choose to melee action = ActionEnum.Attack; // turn towards the player angle = player.Angle; } } // 0.a is there a weapon within view ElementProximity weapon = null; if (!closest.TryGetValue(typeof(AK47), out weapon)) { if (!closest.TryGetValue(typeof(Pistol), out weapon)) { if (!closest.TryGetValue(typeof(Shotgun), out weapon)) { } } } if (weapon != null) { // there is a weapon either close or touching if (IsTouching(weapon, Width / 2)) { // choose to pickup action = ActionEnum.Pickup; // set direction via another decision PreviousPickupId = weapon.Id; } else { // choose action via another decision angle = weapon.Angle; } } } // if there are too many players, then run away if (playerCount >= 5) { // choose an angle opposite from where the center of the other players are angle = Collision.CalculateAngleFromPoint(X, Y, playerX, playerY); // go the opposite way angle = (angle + 180) % 360; } // choose defaults if (action == ActionEnum.None) { // default to move action = ActionEnum.Move; } // check if we are in the Zone if (inZone) { // we should be moving towards the center if (action == ActionEnum.Move) { // eek we are in the zone, indicate that we should be moving towards the center angle = angleToCenter; } } // check if we seem to be stuck if (IsStuck()) { // take some corrective action if (ShowDiagnostics) { System.Diagnostics.Debug.WriteLine("AI seems stuck"); } // try something new angle = Rand.Next() % 360; CorrectiveAngle = 0; } // check if our last movement was obstructed float moveAngle = (angle + CorrectiveAngle) % 360; if (CorrectiveAngle > 0) { CorrectiveAngle -= 15; } if (CorrectiveAngle < 0) { CorrectiveAngle = 0; } // save angle for next time PreviousAngle = moveAngle; // set course float x1, y1, x2, y2; Collision.CalculateLineByAngle(X, Y, moveAngle, 1, out x1, out y1, out x2, out y2); xdelta = x2 - x1; ydelta = y2 - y1; // normalize var sum = (float)(Math.Abs(xdelta) + Math.Abs(ydelta)); xdelta = xdelta / sum; ydelta = ydelta / sum; if (Math.Abs(xdelta) + Math.Abs(ydelta) > 1.0001) { throw new Exception("Invalid xdelta,ydelta : " + xdelta + "," + ydelta); } if (ShowDiagnostics) { System.Diagnostics.Debug.WriteLine("AI {0} {1} {2} {3}", action, angle, xdelta, ydelta); } // if our action is to move... do a melee while moving if (action == ActionEnum.Move && shouldMelee) { return(ActionEnum.Attack); } else { return(action); } }
public override ActionEnum Action(List <Element> elements, float angleToCenter, bool inZone, ref float xdelta, ref float ydelta, ref float angle) { // check if last action failed if (LastActionFailed > 0) { LastActionFailed--; xdelta = Xdelta; ydelta = Ydelta; return(ActionEnum.Move); } // construct a view of the current world var data = new TrainingData() { // core data CenterAngle = angleToCenter, InZone = inZone, Health = Health, Shield = Shield, Z = Z, Primary = Primary != null?Primary.GetType().Name : "", PrimaryAmmo = Primary != null ? Primary.Ammo : 0, PrimaryClip = Primary != null ? Primary.Clip : 0, Secondary = Secondary != null?Secondary.GetType().Name : "", SecondaryAmmo = Secondary != null ? Secondary.Ammo : 0, SecondaryClip = Secondary != null ? Secondary.Clip : 0 }; data.Proximity = AITraining.ComputeProximity(this, elements).Values.ToList(); // use the model to predict its actions var modeldataset = data.AsModelDataSet(); int iAction = 0; { iAction = (int)Math.Round(ActionModel.Predict(modeldataset)); angle = AngleModel.Predict(modeldataset); XYModel.Predict(modeldataset, out xdelta, out ydelta); } // do some sanity checking... if (iAction < 0 || iAction >= (int)ActionEnum.COUNT) { iAction = (int)ActionEnum.Move; } if (Math.Abs(xdelta) + Math.Abs(ydelta) > 1.00001) { throw new Exception("xdelta and ydelta are invalid"); } if (angle < 0) { angle += 360; } if (angle > 360) { angle -= 360; } if (angle < 0 || angle > 360) { throw new Exception("Invalid angle: " + angle); } return((ActionEnum)iAction); }
public override ActionEnum Action(List <Element> elements, float angleToCenter, bool inZone, ref float xdelta, ref float ydelta, ref float zdelta, ref float angle) { // check if last action failed if (LastActionFailed > 0) { LastActionFailed--; xdelta = Xdelta; ydelta = Ydelta; return(ActionEnum.Move); } // construct a view of the current world var pname = ""; var pammo = 0; var pclip = 0; var sname = ""; var sammo = 0; var sclip = 0; if (Primary != null && Primary is RangeWeapon) { pname = Primary.GetType().Name; pammo = (Primary as RangeWeapon).Ammo; pclip = (Primary as RangeWeapon).Clip; } if (Secondary != null && Secondary.Length == 1 && Secondary[0] != null && Secondary[0] is RangeWeapon) { sname = Secondary.GetType().Name; sammo = (Secondary[0] as RangeWeapon).Ammo; sclip = (Secondary[0] as RangeWeapon).Clip; } var data = new TrainingData() { // core data CenterAngle = angleToCenter, InZone = inZone, Health = Health, Shield = Shield, Z = Z, Primary = pname, PrimaryAmmo = pammo, PrimaryClip = pclip, Secondary = sname, SecondaryAmmo = sammo, SecondaryClip = sclip }; data.Proximity = AITraining.ComputeProximity(this, elements).Values.ToList(); // use the model to predict its actions var modeldataset = data.AsModelDataSet(); int iAction = 0; { iAction = (int)Math.Round(ActionModel.Predict(modeldataset)); angle = AngleModel.Predict(modeldataset); XYModel.Predict(modeldataset, out xdelta, out ydelta); } // do some sanity checking... if (iAction < 0 || iAction >= (int)ActionEnum.COUNT) { iAction = (int)ActionEnum.Move; } if (Math.Abs(xdelta) + Math.Abs(ydelta) > 1.00001) { throw new Exception("xdelta and ydelta are invalid"); } while (angle < 0) { angle += 360; } while (angle >= 360) { angle -= 360; } if (angle < 0 || angle >= 360) { throw new Exception("Invalid angle: " + angle); } return((ActionEnum)iAction); }