/// <summary> /// Calculate the potential of the specified field/position. /// </summary> /// <param name="squad"></param> /// <param name="enemy"></param> /// <param name="field"></param> /// <returns></returns> public double CalculatePotentialField(List<UnitAgent> squad, Unit enemy, Position field) { double pVal = 0; //DO NOT UPDATE WITH EVOLUTIONARY ALGORITHM const double forceNeutralUnitsRepulsion = 200; // 0 - 1000 //REMEMBER TO SET TO A POSITIVE NUMBER. const double forceStepNeutralUnitsRepulsion = 1.2; // 0 - 10 int rangeNeutralUnitsRepulsion = 8; //0-512 // /////////////////////////////////////////// double distance = enemy.GetDistanceToPosition(field); if (MyUnit.WeaponGroundCooldown == 0) //If the weapon is ready to fire, PFMaxShootingDistanceAttraction is activated pVal += PFMaxShootingDistanceAttraction(distance, enemy, OptimizedProperties.ForceMSD, OptimizedProperties.ForceStepMSD);//, MSDDiffDivValue); else if (MyUnit.UnitType.AttackRange > 1) //Else If Weapon is ready to fire and AttackRange is bigger than 1, FLEE/RETREAT until weapon is ready to fire again. pVal += PFWeaponCoolDownRepulsion(field, distance, enemy, OptimizedProperties.ForceWeaponCoolDownRepulsion, OptimizedProperties.ForceStepWeaponCoolDownRepulsion, OptimizedProperties.RangeWeaponCooldownRepulsion); //Squad attraction if (squad.Count>2) pVal += PFSquadAttraction(squad, field, OptimizedProperties.ForceSquadAttraction, OptimizedProperties.ForceStepSquadAttraction, OptimizedProperties.RangePercentageSquadAttraction); //Center of the map attraction (NEGATES the MSD) pVal += PFMapCenterAttraction(field, OptimizedProperties.ForceMapCenterAttraction, OptimizedProperties.ForceStepMapCenterAttraction, OptimizedProperties.RangePecentageMapCenterAttraction); //Map edge repulsion (NEGATES the MSD) pVal += MyMath.CalculateMapEdgeRepulsion(field, OptimizedProperties.ForceMapEdgeRepulsion, OptimizedProperties.ForceStepMapEdgeRepulsion, OptimizedProperties.RangeMapEdgeRepulsion); //Own Unit Repulsion pVal += PFOwnUnitsRepulsion(squad, field, OptimizedProperties.ForceOwnUnitsRepulsion, OptimizedProperties.ForceStepOwnUnitsRepulsion, OptimizedProperties.RangeOwnUnitsRepulsion); //Enemy Unit Repulsion pVal += PFEnemyUnitsRepulsion(field, OptimizedProperties.ForceEnemyUnitsRepulsion, OptimizedProperties.ForceStepEnemyUnitsRepulsion);//, rangeEnemyUnitsRepulsion); //Neutral Unit Repulsion pVal += PFNeutralUnitsRepulsion(field, forceNeutralUnitsRepulsion, forceStepNeutralUnitsRepulsion, rangeNeutralUnitsRepulsion); return pVal; }
/// <summary> /// Calculates the potential field repulsion value from a neutral unit. /// Flying neutral units will be ignored and return 0. /// All other neutral units will use this formula: -(force - forceStep * distance). /// Inspiration from: BTHAI StarCraft bot ver. 1.00 calcMineP method. /// </summary> /// <param name="field"></param> /// <param name="neutralUnit"></param> /// <param name="force"></param> /// <param name="forceStep"></param> /// <param name="range"></param> /// <returns></returns> public static double CalculatePFNeutralUnitRepulsion(Unit neutralUnit, Position field, double force, double forceStep, int range) { double distance = neutralUnit.GetDistanceToPosition(field); if (neutralUnit.UnitType.IsFlyer) return 0; if (neutralUnit.UnitType.IsBuildingFlying) return 0; return distance <= GetUnitSize(neutralUnit.UnitType) + range ? CalculateRepulsiveMagnitude(force, forceStep, distance, false) : 0; }
/// <summary> /// /// </summary> /// <param name="unit"></param> /// <param name="field"></param> /// <param name="enemyUnit"></param> /// <param name="force"></param> /// <param name="forceStep"></param> /// <param name="range"></param> /// <returns></returns> public static double CalculatePFEnemyUnitRepulsion(Unit unit, Position field, Unit enemyUnit, double force, double forceStep) { if (unit.ID == enemyUnit.ID)//If both units has the same ID, there can't be a collision, so don't calculate anything. return 0; double distance = enemyUnit.GetDistanceToPosition(field); int myUnitMSD = unit.UnitType.WeaponGround.AttackRangeMax; int enemyUnitMSD = enemyUnit.UnitType.WeaponGround.AttackRangeMax; int MSDDifference = myUnitMSD - enemyUnitMSD; if (MSDDifference > 0) { if (distance <= enemyUnitMSD) return CalculateRepulsiveMagnitude(force, forceStep, distance, false);//-20; } else if (distance <= GetUnitSize(unit.UnitType)) return -force; return 0; }
/// <summary> /// Used for Potential Fields /// Calculates if a two of my own units is standing too close to each other. /// Best PF value is 0 (No risk for collision with own units). Lower values if there is risk of splash damage or collision with other units. /// There is a special case for cloaked ground units: They should avoid getting to close to none cloaked units (to avoid splash damage). /// Inspiration from BTHAI StarCraft bot ver. 1.00 method calcOwnUnitP: http://code.google.com/p/bthai/ /// </summary> /// <param name="unit"></param> /// <param name="field"></param> /// <param name="myOtherUnit"></param> /// <param name="force"></param> /// <param name="forceStep">Should always be lower than punishment</param> /// <param name="range"></param> /// <returns></returns> public static double CalculatePFOwnUnitRepulsion(Unit unit, Position field, Unit myOtherUnit, double force, double forceStep, int range) { double distance = myOtherUnit.GetDistanceToPosition(field); if (unit.ID == myOtherUnit.ID || unit.UnitType.IsFlyer || myOtherUnit.UnitType.IsFlyer || unit.UnitType.IsBuildingFlying || myOtherUnit.UnitType.IsBuildingFlying)//If both units has the same ID, there can't be a collision, so don't calculate anything. return 0; if (myOtherUnit.UnitTypeEnum == UnitTypes.Terran_VultureSpiderMine) if (distance <= 125 + GetUnitSize(unit.UnitType))//Avoid Spider Mines. return CalculateRepulsiveMagnitude(force, forceStep, distance, false);//-20; if (unit.IsCloaked && !myOtherUnit.IsCloaked) //Cloak units should avoid standing to close to other non cloaked units to avoid splash damage from tanks for instance. if (distance <= 50 + GetUnitSize(unit.UnitType)) return CalculateRepulsiveMagnitude(force, forceStep, distance, false);//-20; //OPTIMIZE BY EVOLUTIONARY COMPUTATION return distance <= GetUnitSize(unit.UnitType) + range ? CalculateRepulsiveMagnitude(force, forceStep, distance, false) : 0; }