Exemplo n.º 1
0
 /*
 ====================================================================
 Evaluate a unit's attack against target.
   score_base: basic score for attacking
   score_rugged: score added for each rugged def point (0-100)
                 of target
   score_kill: score unit receives for each (expected) point of
               strength damage done to target
   score_loss: score that is substracted per strength point
               unit is expected to loose
 The final score is stored to 'result' and True if returned if the
 attack may be performed else False.
 ====================================================================
 */
 static bool unit_evaluate_attack(Unit unit, Unit target, int score_base, int score_rugged, int score_kill, int score_loss, out int result)
 {
     int unit_dam = 0, target_dam = 0, rugged_def = 0;
     result = 0;
     if (!unit.CheckAttack(  target, Unit.UNIT_ATTACK.UNIT_ACTIVE_ATTACK)) return false;
     Unit.GetExpectedLosses(unit, target, out unit_dam, out target_dam);
     if (unit.CheckRuggedDefense( target))
         rugged_def = unit.GetRuggedDefenseChance( target);
     if (rugged_def < 0) rugged_def = 0;
     result = score_base + rugged_def * score_rugged + target_dam * score_kill + unit_dam * score_loss;
     #if DEBUG
     Console.WriteLine("  {0}: {1}: bas:{2}, rug:{3}, kil:{4}, los: {5} = {6}", unit.name, target.name,
     score_base,
     rugged_def * score_rugged,
     target_dam * score_kill,
     unit_dam * score_loss, result);
     #endif
     /* if target is a df unit give a small bonus */
     if (((target.sel_prop.flags & UnitFlags.ARTILLERY) == UnitFlags.ARTILLERY) ||
         ((target.sel_prop.flags & UnitFlags.AIR_DEFENSE) == UnitFlags.AIR_DEFENSE))
         result += score_kill;
     return true;
 }
Exemplo n.º 2
0
 public FIGHT_TYPES Attack(Unit target, UNIT_ATTACK type, bool real, bool force_rugged)
 {
     int unit_old_str = this.str;//, target_old_str = target.str;
     int unit_old_ini = this.sel_prop.ini, target_old_ini = target.sel_prop.ini;
     int unit_dam = 0, unit_suppr = 0, target_dam = 0, target_suppr = 0;
     int rugged_chance;
     bool rugged_def = false;
     int exp_mod;
     FIGHT_TYPES ret = FIGHT_TYPES.AR_NONE; /* clear flags */
     ATTACK_FLAGS strike;
     /* check if rugged defense occurs */
     if (real && type == UNIT_ATTACK.UNIT_ACTIVE_ATTACK)
         if (this.CheckRuggedDefense(target) || (force_rugged && this.IsClose(target)))
         {
             rugged_chance = this.GetRuggedDefenseChance(target);
             if (Misc.DICE(100) <= rugged_chance || force_rugged)
                 rugged_def = true;
         }
     /* PG's formula for initiative is
        min { base initiative, terrain max initiative } +
        ( exp_level + 1 ) / 2 + D3 */
     /* against aircrafts the initiative is used since terrain does not matter */
     /* target's terrain is used for fight */
     if ((this.sel_prop.flags & UnitFlags.FLYING) != UnitFlags.FLYING &&
         (target.sel_prop.flags & UnitFlags.FLYING) != UnitFlags.FLYING)
     {
         this.sel_prop.ini = Math.Min(this.sel_prop.ini, target.terrain.max_ini);
         target.sel_prop.ini = Math.Min(target.sel_prop.ini, target.terrain.max_ini);
     }
     this.sel_prop.ini += (this.exp_level + 1) / 2;
     target.sel_prop.ini += (target.exp_level + 1) / 2;
     /* special initiative rules:
        antitank inits attack tank|recon: atk 0, def 99
        tank inits attack against anti-tank: atk 0, def 99
        defensive fire: atk 99, def 0
        submarine attacks: atk 99, def 0
        ranged attack: atk 99, def 0
        rugged defense: atk 0
        air unit attacks air defense: atk = def
        non-art vs art: atk 0, def 99 */
     if ((this.sel_prop.flags & UnitFlags.ANTI_TANK) == UnitFlags.ANTI_TANK)
         if ((target.sel_prop.flags & UnitFlags.TANK) == UnitFlags.TANK)
         {
             this.sel_prop.ini = 0;
             target.sel_prop.ini = 99;
         }
     if (((this.sel_prop.flags & UnitFlags.DIVING) == UnitFlags.DIVING) ||
          ((this.sel_prop.flags & UnitFlags.ARTILLERY) == UnitFlags.ARTILLERY) ||
          ((this.sel_prop.flags & UnitFlags.AIR_DEFENSE) == UnitFlags.AIR_DEFENSE) ||
          type == UNIT_ATTACK.UNIT_DEFENSIVE_ATTACK
     )
     {
         this.sel_prop.ini = 99;
         target.sel_prop.ini = 0;
     }
     if ((this.sel_prop.flags & UnitFlags.FLYING) == UnitFlags.FLYING)
         if ((target.sel_prop.flags & UnitFlags.AIR_DEFENSE) == UnitFlags.AIR_DEFENSE)
             this.sel_prop.ini = target.sel_prop.ini;
     if (rugged_def)
         this.sel_prop.ini = 0;
     if (force_rugged)
         target.sel_prop.ini = 99;
     /* the dice is rolled after these changes */
     if (real)
     {
         this.sel_prop.ini += Misc.DICE(3);
         target.sel_prop.ini += Misc.DICE(3);
     }
     #if DEBUG
     if (real)
     {
         Console.WriteLine("{0} Initiative: {1}", this.name, this.sel_prop.ini);
         Console.WriteLine("{0} Initiative: {1}", target.name, target.sel_prop.ini);
         if (this.CheckRuggedDefense(target))
             Console.WriteLine("Rugged Defense: {0} ({1})",
                     rugged_def ? "yes" : "no",
                     this.GetRuggedDefenseChance(target));
     }
     #endif
     /* in a real combat a submarine may evade */
     if (real && type == UNIT_ATTACK.UNIT_ACTIVE_ATTACK && ((target.sel_prop.flags & UnitFlags.DIVING) == UnitFlags.DIVING))
     {
         if (Misc.DICE(10) <= 7 + (target.exp_level - this.exp_level) / 2)
         {
             strike = ATTACK_FLAGS.ATK_NO_STRIKE;
             ret |= FIGHT_TYPES.AR_EVADED;
         }
         else
             strike = ATTACK_FLAGS.ATK_UNIT_FIRST;
     #if DEBUG
         Console.WriteLine("\nSubmarine Evasion: {0} ({1}%)\n",
          (strike == ATTACK_FLAGS.ATK_NO_STRIKE) ? "yes" : "no",
          10 * (7 + (target.exp_level - this.exp_level) / 2));
     #endif
     }
     else
         /* who is first? */
         if (this.sel_prop.ini == target.sel_prop.ini)
             strike = ATTACK_FLAGS.ATK_BOTH_STRIKE;
         else
             if (this.sel_prop.ini > target.sel_prop.ini)
                 strike = ATTACK_FLAGS.ATK_UNIT_FIRST;
             else
                 strike = ATTACK_FLAGS.ATK_TARGET_FIRST;
     /* the one with the highest initiative begins first if not defensive fire or artillery */
     if (strike == ATTACK_FLAGS.ATK_BOTH_STRIKE)
     {
         /* both strike at the same time */
         GetDamage(this, this, target, type, real, rugged_def, out target_dam, out target_suppr);
         if (target.CheckAttack(this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK))
             GetDamage(this, target, this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK, real, rugged_def, out unit_dam, out unit_suppr);
         target.ApplyDamage(target_dam, target_suppr, this);
         this.ApplyDamage(unit_dam, unit_suppr, target);
     }
     else
         if (strike == ATTACK_FLAGS.ATK_UNIT_FIRST)
         {
             /* unit strikes first */
             GetDamage(this, this, target, type, real, rugged_def, out target_dam, out target_suppr);
             if (target.ApplyDamage(target_dam, target_suppr, this) != 0)
                 if (target.CheckAttack(this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK) && type != UNIT_ATTACK.UNIT_DEFENSIVE_ATTACK)
                 {
                     GetDamage(this, target, this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK, real, rugged_def, out unit_dam, out unit_suppr);
                     this.ApplyDamage(unit_dam, unit_suppr, target);
                 }
         }
         else
             if (strike == ATTACK_FLAGS.ATK_TARGET_FIRST)
             {
                 /* target strikes first */
                 if (target.CheckAttack(this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK))
                 {
                     GetDamage(this, target, this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK, real, rugged_def, out unit_dam, out unit_suppr);
                     if (this.ApplyDamage(unit_dam, unit_suppr, target) == 0)
                         ret |= FIGHT_TYPES.AR_UNIT_ATTACK_BROKEN_UP;
                 }
                 if (unit_get_cur_str(this) > 0)
                 {
                     GetDamage(this, this, target, type, real, rugged_def, out target_dam, out target_suppr);
                     target.ApplyDamage(target_dam, target_suppr, this);
                 }
             }
     /* check return value */
     if (this.str == 0)
         ret |= FIGHT_TYPES.AR_UNIT_KILLED;
     else
         if (unit_get_cur_str(this) == 0)
             ret |= FIGHT_TYPES.AR_UNIT_SUPPRESSED;
     if (target.str == 0)
         ret |= FIGHT_TYPES.AR_TARGET_KILLED;
     else
         if (unit_get_cur_str(target) == 0)
             ret |= FIGHT_TYPES.AR_TARGET_SUPPRESSED;
     if (rugged_def)
         ret |= FIGHT_TYPES.AR_RUGGED_DEFENSE;
     if (real)
     {
         /* cost ammo */
         if (Config.supply)
         {
             //if (DICE(10)<=target_old_str)
             this.cur_ammo--;
             if (target.CheckAttack(this, UNIT_ATTACK.UNIT_PASSIVE_ATTACK) && target.cur_ammo > 0)
                 //if (DICE(10)<=unit_old_str)
                 target.cur_ammo--;
         }
         /* costs attack */
         if (this.cur_atk_count > 0) this.cur_atk_count--;
         /* target: loose entrenchment if damage was taken or with a unit.str*10% chance */
         if (target.entr > 0)
             if (target_dam > 0 || Misc.DICE(10) <= unit_old_str)
                 target.entr--;
         /* attacker looses entrenchment if it got hurt */
         if (this.entr > 0 && unit_dam > 0)
             this.entr--;
         /* gain experience */
         exp_mod = target.exp_level - this.exp_level;
         if (exp_mod < 1) exp_mod = 1;
         this.AddExperience(exp_mod * target_dam + unit_dam);
         exp_mod = this.exp_level - target.exp_level;
         if (exp_mod < 1) exp_mod = 1;
         target.AddExperience(exp_mod * unit_dam + target_dam);
         if (this.IsClose(target))
         {
             this.AddExperience(10);
             target.AddExperience(10);
         }
         /* adjust life bars */
         update_bar(this);
         update_bar(target);
     }
     this.sel_prop.ini = unit_old_ini;
     target.sel_prop.ini = target_old_ini;
     return ret;
 }