예제 #1
0
        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();
        }
예제 #2
0
        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();
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
파일: TrainedAI.cs 프로젝트: Onin1/shootmup
        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);
        }
예제 #5
0
        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);
        }