Advertisement
aaaaaa123456789

Fitness calculation (gen 1)

Feb 12th, 2018
578
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 21.00 KB | None | 0 0
  1. typedef struct {
  2.   struct {
  3.     unsigned char id;
  4.     unsigned char national_dex;
  5.     unsigned char typenum1, typenum2;
  6.     struct small_stats {
  7.       unsigned char hp, attack, defense, special_attack, special_defense, speed;
  8.     } base_stats;
  9.   } species;
  10.   unsigned char level;
  11.   unsigned experience;
  12.   struct small_stats ivs;
  13.   struct stats {
  14.     unsigned short hp, attack, defense, special_attack, special_defense, speed;
  15.   } evs;
  16.   struct {
  17.     unsigned char id;
  18.     unsigned char pp;
  19.     unsigned char pp_ups;
  20.   } moves[4];
  21. } Pokemon;
  22.  
  23. struct {
  24.   unsigned char power;
  25.   signed char effect_code;
  26.   unsigned char hit_chance; // out of 256
  27.   unsigned char type;
  28. } move_data[] = {
  29.   {  0,  0,   0,  0},
  30.   { 40,  0, 255,  0},
  31.   { 50, -1, 255,  0},
  32.   { 15, 29, 216,  0},
  33.   { 18, 29, 216,  0},
  34.   { 80,  0, 216,  0},
  35.   { 40, 16, 255,  0},
  36.   { 75,  4, 255, 20},
  37.   { 75,  5, 255, 25},
  38.   { 75,  6, 255, 23},
  39.   { 40,  0, 255,  0},
  40.   { 55,  0, 255,  0},
  41.   {  1, 38,  76,  0},
  42.   { 80, 39, 191,  0},
  43.   {  0, 50, 255,  0},
  44.   { 50,  0, 242,  0},
  45.   { 40,  0, 255,  0},
  46.   { 35,  0, 255,  2},
  47.   {  0, 28, 216,  0},
  48.   { 70, 43, 242,  2},
  49.   { 15, 42, 191,  0},
  50.   { 80,  0, 191,  0},
  51.   { 35,  0, 255, 22},
  52.   { 65, 37, 255,  0},
  53.   { 30, 44, 255,  1},
  54.   {120,  0, 191,  0},
  55.   { 70, 45, 242,  1},
  56.   { 60, 37, 216,  1},
  57.   {  0, 22, 255,  0},
  58.   { 70, 37, 255,  0},
  59.   { 65,  0, 255,  0},
  60.   { 15, 29, 216,  0},
  61.   {  1, 38,  76,  0},
  62.   { 35,  0, 242,  0},
  63.   { 85, 36, 255,  0},
  64.   { 15, 42, 216,  0},
  65.   { 90, 48, 216,  0},
  66.   { 90, 27, 255,  0},
  67.   {100, 48, 255,  0},
  68.   {  0, 19, 255,  0},
  69.   { 15,  2, 255,  3},
  70.   { 25, 75, 255,  7},
  71.   { 14, 29, 216,  7},
  72.   {  0, 19, 255,  0},
  73.   { 60, 31, 255,  0},
  74.   {  0, 18, 255,  0},
  75.   {  0, 28, 255,  0},
  76.   {  0, 32, 140,  0},
  77.   {  0, 49, 140,  0},
  78.   { 20, 41, 229,  0}, // set power to 20 to help calculations
  79.   {  0, 86, 140,  0},
  80.   { 40, 69, 255,  3},
  81.   { 40,  4, 255, 20},
  82.   { 95,  4, 255, 20},
  83.   {  0, 46, 255, 25},
  84.   { 40,  0, 255, 21},
  85.   {120,  0, 204, 21},
  86.   { 95,  0, 255, 21},
  87.   { 95,  5, 255, 25},
  88.   {120,  5, 229, 25},
  89.   { 65, 49, 255, 24},
  90.   { 65, 71, 255, 21},
  91.   { 65, 68, 255, 25},
  92.   {150, 80, 229,  0},
  93.   { 35,  0, 255,  2},
  94.   { 80,  0, 255,  2},
  95.   { 80, 48, 204,  1},
  96.   { 50, 37, 229,  1},
  97.   {  1, -7, 255,  1},
  98.   {  1, -4, 255,  1},
  99.   { 80,  0, 255,  0},
  100.   { 20,  3, 255, 22},
  101.   { 40,  3, 255, 22},
  102.   {  0, 84, 229, 22},
  103.   {  0, 12, 255,  0},
  104.   { 55, -1, 242, 22},
  105.   {120, 39, 255, 22},
  106.   {  0, 66, 191,  3},
  107.   {  0, 67, 191, 22},
  108.   {  0, 32, 191, 22},
  109.   { 70, 27, 255, 22},
  110.   {  0, 20, 242,  7},
  111.   { 40, 41, 255, 26}, // set power to 40 to help calculations
  112.   { 15, 42, 178, 20},
  113.   { 40,  6, 255, 23},
  114.   { 95,  6, 255, 23},
  115.   {  0, 67, 255, 23},
  116.   {120,  6, 178, 23},
  117.   { 50,  0, 165,  5},
  118.   {100,  0, 255,  4},
  119.   {  1, 38,  76,  4},
  120.   {100, 39, 255,  4},
  121.   {  0, -2, 216,  3},
  122.   { 50, 76, 255, 24},
  123.   { 90, 71, 255, 24},
  124.   {  0, 32, 153, 24},
  125.   {  0, 10, 255, 24},
  126.   {  0, 52, 255, 24},
  127.   { 40, -3, 255,  0},
  128.   { 20, 81, 255,  0},
  129.   {  0, 28, 255, 24},
  130.   {  0, -4, 255,  8},
  131.   {  0, 82, 255,  0},
  132.   {  0, 59, 216,  0},
  133.   {  0, 15, 255,  0},
  134.   {  0, 56, 255,  0},
  135.   {  0, 11, 255,  0},
  136.   {  0, 15, 255,  0},
  137.   {  0, 22, 255,  0},
  138.   {  0, 49, 255,  8},
  139.   {  0, 11, 255, 21},
  140.   {  0, 11, 255,  0},
  141.   {  0, 51, 255, 24},
  142.   {  0, 64, 255, 24},
  143.   {  0, 25, 255, 25},
  144.   {  0, 65, 255, 24},
  145.   {  0, 47, 255,  0},
  146.   {  0, 26, 255,  0},
  147.   {  0, 83, 255,  0},
  148.   {  0,  9, 255,  2},
  149.   {130,  7, 255,  0},
  150.   {100,  0, 191,  0},
  151.   { 20, 36, 255,  8},
  152.   { 20, 33, 178,  3},
  153.   { 65, 33, 255,  3},
  154.   { 65, 31, 216,  4},
  155.   {120, 34, 216, 20},
  156.   { 80,  0, 255, 21},
  157.   { 35, 42, 191, 21},
  158.   { 60, 17, 255,  0},
  159.   {100, 39, 255,  0},
  160.   { 20, 29, 255,  0},
  161.   { 10, 70, 255,  0},
  162.   {  0, 53, 255, 24},
  163.   {  0, 22, 204, 24},
  164.   {  0, 56, 255,  0},
  165.   { 85, 45, 229,  1},
  166.   {  0, 67, 191,  0},
  167.   {100,  8, 255, 24},
  168.   {  0, 66, 140,  3},
  169.   { 15, 29, 216,  0},
  170.   { 20,  3, 255,  7},
  171.   {  0, 32, 191,  0},
  172.   {140, 39, 229,  2},
  173.   {  0, 57, 255,  0},
  174.   { 20, 70, 255, 21},
  175.   { 70,  0, 255,  0},
  176.   {  0, 32, 255, 22},
  177.   {  0, 22, 178,  0},
  178.   {  1, -5, 204, 24},
  179.   {  0, 85, 255,  0},
  180.   {  0, 51, 255,  3},
  181.   { 90, -1, 216, 21},
  182.   {170,  7, 255,  0},
  183.   { 18, 29, 204,  0},
  184.   { 50, 44, 229,  4},
  185.   {  0, -6, 255, 24},
  186.   { 75,  0, 229,  5},
  187.   { 80, 31, 229,  0},
  188.   {  0, 10, 255,  0},
  189.   {  0, 24, 255,  0},
  190.   { 80,  0, 255,  0},
  191.   {  1, 40, 229,  0},
  192.   { 70, -1, 255,  0},
  193.   {  0, 79, 255,  0},
  194.   { 50, 48, 255,  0}
  195. };
  196.  
  197. // assign power-like values to various effects that moves may have
  198. #define POISON_VALUE            15
  199. #define PARALYSIS_VALUE         10
  200. #define SLEEP_VALUE             20
  201. #define BURN_VALUE              15
  202. #define FREEZE_VALUE           100
  203. #define CONFUSION_VALUE         30
  204. #define STAT_UP_VALUE            5
  205. #define STAT_DOWN_VALUE          5
  206. #define SCREEN_VALUE            20
  207. #define FLINCH_VALUE            15
  208. #define FAINT_VALUE            300
  209. #define HEAL_VALUE              80
  210. #define VULNERABLE_TURN_VALUE   15
  211. #define SUBSTITUTE_VALUE        30
  212. #define LEECH_SEED_VALUE        20
  213. #define DISABLE_VALUE           20
  214. #define PRIORITY_VALUE           5
  215.  
  216. #define FLAG_DANGEROUS       (1 << 0)  /* the user will probably hurt itself just by having this move */
  217. #define FLAG_BAD_MOVE_CHOICE (1 << 1)  /* the user will probably use this move incorrectly and waste a turn */
  218. #define FLAG_IGNORE          (1 << 2)  /* this move should not be taken into account when assessing damaging potential */
  219. #define FLAG_NO_STAB         (1 << 3)  /* the user will not get STAB reliably due to this move existing */
  220. #define FLAG_IGNORE_STAB     (1 << 4)  /* this move cannot get STAB */
  221. #define FLAG_EXACT_DAMAGE    (1 << 5)  /* the computed move power is this move's exact damage output */
  222. #define FLAG_TRANSFORM       (1 << 6)  /* this move makes the user adopt its opponent's stats and moves */
  223. #define FLAG_LEVEL_DAMAGE    (1 << 7)  /* this move's damage is equal to the level of the user */
  224. #define FLAG_HIGH_CRIT_RATIO (1 << 8)  /* this move has a high critical hit ratio */
  225. #define FLAG_LOW_CRIT_CHANCE (1 << 9)  /* a mon with this move will have a low crit chance, since it's likely to use the move and lower its own crit ratio */
  226. #define FLAG_NO_CRITICALS    (1 << 10) /* this attack cannot ever result in a critical hit */
  227.  
  228. struct move_effect_data {
  229.   unsigned short flags;
  230.   short multiply_offset; // implicit 256 denominator
  231.   int add_offset; // implicit 256 denominator
  232. };
  233.  
  234. struct move_effect_data effect_code_data[] = {
  235.   // note that all omitted fields default to zero
  236.   {0}, // all fields zero
  237.   {0}, // unused
  238.   {.add_offset = POISON_VALUE * 51},
  239.   {.multiply_offset = 128},
  240.   {.add_offset = BURN_VALUE * 25},
  241.   {.add_offset = FREEZE_VALUE * 25},
  242.   {.add_offset = PARALYSIS_VALUE * 25},
  243.   {.multiply_offset = 256, .add_offset = -FAINT_VALUE * 256, .flags = FLAG_DANGEROUS},
  244.   {.multiply_offset = -192, .flags = FLAG_BAD_MOVE_CHOICE},
  245.   {.flags = FLAG_IGNORE},
  246.   {.add_offset = STAT_UP_VALUE * 256},
  247.   {.add_offset = STAT_UP_VALUE * 256},
  248.   {.add_offset = STAT_UP_VALUE * 256},
  249.   {.add_offset = STAT_UP_VALUE * 256},
  250.   {.add_offset = STAT_UP_VALUE * 256},
  251.   {.add_offset = STAT_UP_VALUE * 256},
  252.   {0}, // same as no effect
  253.   {.multiply_offset = 13}, // +5% for perfect accuracy
  254.   {.add_offset = STAT_DOWN_VALUE * 256},
  255.   {.add_offset = STAT_DOWN_VALUE * 256},
  256.   {.add_offset = STAT_DOWN_VALUE * 256},
  257.   {.add_offset = STAT_DOWN_VALUE * 256},
  258.   {.add_offset = STAT_DOWN_VALUE * 256},
  259.   {.add_offset = STAT_DOWN_VALUE * 256},
  260.   {.flags = FLAG_IGNORE | FLAG_NO_STAB},
  261.   {.flags = FLAG_BAD_MOVE_CHOICE},
  262.   {.flags = FLAG_IGNORE | FLAG_BAD_MOVE_CHOICE},
  263.   {.add_offset = -CONFUSION_VALUE * 73}, // will only confuse self after 3.5 turns in average
  264.   {.flags = FLAG_IGNORE | FLAG_BAD_MOVE_CHOICE},
  265.   {.multiply_offset = 2 * 256}, // * 3
  266.   {0}, // unused
  267.   {.add_offset = FLINCH_VALUE * 25},
  268.   {.add_offset = SLEEP_VALUE * 256},
  269.   {.add_offset = POISON_VALUE * 102},
  270.   {.add_offset = BURN_VALUE * 76},
  271.   {0}, // unused
  272.   {.add_offset = PARALYSIS_VALUE * 76},
  273.   {.add_offset = FLINCH_VALUE * 76},
  274.   {.multiply_offset = -256, .add_offset = FAINT_VALUE * 256, .flags = FLAG_BAD_MOVE_CHOICE | FLAG_IGNORE_STAB | FLAG_NO_CRITICALS},
  275.   {.multiply_offset = -128, .add_offset = -VULNERABLE_TURN_VALUE * 256},
  276.   {.multiply_offset = -256, .add_offset = FAINT_VALUE * 64, .flags = FLAG_IGNORE_STAB | FLAG_NO_CRITICALS},
  277.   {.flags = FLAG_EXACT_DAMAGE | FLAG_IGNORE_STAB | FLAG_NO_CRITICALS},
  278.   {.multiply_offset = 2 * 256}, // * 3
  279.   {0}, // wasted turn compensates for two-turn move
  280.   {.multiply_offset = 256},
  281.   {0}, // recoil is 1 HP, which doesn't really matter and we can ignore it
  282.   {.flags = FLAG_BAD_MOVE_CHOICE},
  283.   {.flags = FLAG_BAD_MOVE_CHOICE | FLAG_LOW_CRIT_CHANCE},
  284.   {.multiply_offset = -64},
  285.   {.add_offset = CONFUSION_VALUE * 256},
  286.   {.add_offset = 2 * STAT_UP_VALUE * 256},
  287.   {.add_offset = 2 * STAT_UP_VALUE * 256},
  288.   {.add_offset = 2 * STAT_UP_VALUE * 256},
  289.   {.add_offset = 2 * STAT_UP_VALUE * 256},
  290.   {.add_offset = 2 * STAT_UP_VALUE * 256},
  291.   {.add_offset = 2 * STAT_UP_VALUE * 256},
  292.   {.add_offset = HEAL_VALUE * 256, .flags = FLAG_IGNORE_STAB},
  293.   {.flags = FLAG_TRANSFORM}, // we can't use FLAG_IGNORE on Transform because it will usually be the mon's only move
  294.   {.add_offset = 2 * STAT_DOWN_VALUE * 256},
  295.   {.add_offset = 2 * STAT_DOWN_VALUE * 256},
  296.   {.add_offset = 2 * STAT_DOWN_VALUE * 256},
  297.   {.add_offset = 2 * STAT_DOWN_VALUE * 256},
  298.   {.add_offset = 2 * STAT_DOWN_VALUE * 256},
  299.   {.add_offset = 2 * STAT_DOWN_VALUE * 256},
  300.   {.add_offset = SCREEN_VALUE * 256, .flags = FLAG_IGNORE_STAB},
  301.   {.add_offset = SCREEN_VALUE * 256, .flags = FLAG_IGNORE_STAB},
  302.   {.add_offset = POISON_VALUE * 256},
  303.   {.add_offset = PARALYSIS_VALUE * 256},
  304.   {.add_offset = STAT_DOWN_VALUE * 85},
  305.   {.add_offset = STAT_DOWN_VALUE * 85},
  306.   {.add_offset = STAT_DOWN_VALUE * 85},
  307.   {.add_offset = STAT_DOWN_VALUE * 85},
  308.   {0}, // unused
  309.   {0}, // unused
  310.   {0}, // unused
  311.   {0}, // unused
  312.   {.add_offset = CONFUSION_VALUE * 25},
  313.   {.multiply_offset = 256, .add_offset = POISON_VALUE * 51},
  314.   {0}, // unused
  315.   {.add_offset = SUBSTITUTE_VALUE * 256},
  316.   {.multiply_offset = -128, .add_offset = -VULNERABLE_TURN_VALUE * 256},
  317.   {.multiply_offset = 128, .flags = FLAG_DANGEROUS}, // we can expect the average power gain for Rage to be +50%, but it's a bad idea anyway
  318.   {.flags = FLAG_IGNORE}, // Mimic is just a pain to handle
  319.   {.add_offset = 40 * 256, .flags = FLAG_BAD_MOVE_CHOICE}, // 40 power is a reasonable average
  320.   {.add_offset = LEECH_SEED_VALUE * 256},
  321.   {.multiply_offset = -256, .flags = FLAG_BAD_MOVE_CHOICE | FLAG_IGNORE_STAB},
  322.   {.add_offset = DISABLE_VALUE * 256}
  323. };
  324.  
  325. struct move_effect_data custom_effect_data[] = {
  326.   // negative (made up) effect codes go here
  327.   {.flags = FLAG_HIGH_CRIT_RATIO}, // -1: high crit ratio
  328.   {.add_offset = POISON_VALUE * 640}, // -2: toxic (assume poison to be 2.5x as effective)
  329.   {.add_offset = PRIORITY_VALUE * 256}, // -3: quick attack
  330.   {.flags = FLAG_LEVEL_DAMAGE | FLAG_IGNORE_STAB | FLAG_NO_CRITICALS}, // -4: level-based move damage
  331.   {.multiply_offset = -64, .flags = FLAG_LEVEL_DAMAGE | FLAG_IGNORE_STAB | FLAG_NO_CRITICALS}, // -5: psywave (deals 75% of level in average)
  332.   {.add_offset = HEAL_VALUE * 256, .flags = FLAG_BAD_MOVE_CHOICE}, // -6: rest, scored as any heal move but the AI may use it at really bad times
  333.   {.add_offset = 20 * 256, .flags = FLAG_BAD_MOVE_CHOICE | FLAG_NO_CRITICALS} // -7: counter, will deal 20 pow in average, but it's usually a bad choice in gen 1
  334. };
  335.  
  336. unsigned char square_root (unsigned short value) {
  337.   // square roots the gen 1/2 way
  338.   if (value < 3) return value;
  339.   if (value > 64516) return 255;
  340.   unsigned char result;
  341.   for (result = 2; (result * result) < value; result ++);
  342.   return result;
  343. }
  344.  
  345. unsigned short calculate_stat (unsigned char level, unsigned char base, unsigned char DV, unsigned short stat_exp, int is_HP) {
  346.   // remember that shifts truncate! 15 >> 2 is 3, not 3.75
  347.   unsigned growth = 2 * (base + DV) + (square_root(stat_exp) >> 2);
  348.   if (is_HP) growth += 100;
  349.   return (is_HP ? 10 : 5) + growth * level / 100; // also truncates
  350. }
  351.  
  352. struct stats calculate_stats (Pokemon pokemon) {
  353.   return (struct stats) {
  354.     .hp = calculate_stat(pokemon.level, pokemon.species.base_stats.hp, pokemon.ivs.hp, pokemon.evs.hp, 1),
  355.     .attack = calculate_stat(pokemon.level, pokemon.species.base_stats.attack, pokemon.ivs.attack, pokemon.evs.attack, 0),
  356.     .defense = calculate_stat(pokemon.level, pokemon.species.base_stats.defense, pokemon.ivs.defense, pokemon.evs.defense, 0),
  357.     .speed = calculate_stat(pokemon.level, pokemon.species.base_stats.speed, pokemon.ivs.speed, pokemon.evs.speed, 0),
  358.     .special_attack = calculate_stat(pokemon.level, pokemon.species.base_stats.special_attack, pokemon.ivs.special_attack, pokemon.evs.special_attack, 0),
  359.     .special_defense = calculate_stat(pokemon.level, pokemon.species.base_stats.special_defense, pokemon.ivs.special_defense, pokemon.evs.special_defense, 0)
  360.   };
  361. }
  362.  
  363. struct move_effect_data get_move_effect_data (unsigned char move) {
  364.   int effect_code = move_data[move].effect_code;
  365.   if (effect_code >= 0) return effect_code_data[effect_code];
  366.   return custom_effect_data[~effect_code];
  367. }
  368.  
  369. unsigned short get_move_flags (unsigned char move) {
  370.   return get_move_effect_data(move).flags;
  371. }
  372.  
  373. unsigned short get_mon_flags (Pokemon pkmn) {
  374.   return get_move_flags(pkmn.moves -> id) | get_move_flags(pkmn.moves[1].id) | get_move_flags(pkmn.moves[2].id) | get_move_flags(pkmn.moves[3].id);
  375. }
  376.  
  377. unsigned long long calculate_move_power_rating (unsigned char move, Pokemon attacker) {
  378.   // (0.4 * level + 2) * attack stat * power * accuracy, adjusted for crit hit change
  379.   // will contain an implicit shift of 24
  380.   struct stats stats = calculate_stats(attacker);
  381.   struct move_effect_data effect = get_move_effect_data(move);
  382.   int power = move_data[move].power * move_data[move].hit_chance * (256 + effect.multiply_offset);
  383.   unsigned short global_flags = get_mon_flags(attacker);
  384.   unsigned short crit_chance = attacker.species.base_stats.speed >> 1;
  385.   unsigned short attack_stat = (move_data[move].type >= 20) ? stats.special_attack : stats.attack;
  386.   if (effect.flags & FLAG_HIGH_CRIT_RATIO) crit_chance <<= 3;
  387.   if (global_flags & FLAG_LOW_CRIT_CHANCE) crit_chance >>= 2;
  388.   if (crit_chance > 255) crit_chance = 255;
  389.   if (effect.flags & FLAG_LEVEL_DAMAGE) {
  390.     effect.flags |= FLAG_EXACT_DAMAGE;
  391.     power = attacker.level * (256 + effect.multiply_offset) * move_data[move].hit_chance;
  392.   }
  393.   if (effect.flags & FLAG_EXACT_DAMAGE) {
  394.     // at low levels, exact damage is a lot more tempting than at high levels
  395.     // to account for this fact, we take a fixed attack stat value of 100 for damage calculation and pretend they are variable power moves
  396.     effect.flags |= FLAG_IGNORE_STAB | FLAG_NO_CRITICALS;
  397.     attack_stat = 100;
  398.   }
  399.   if (effect.flags & FLAG_NO_CRITICALS) crit_chance = 0;
  400.   if (
  401.       ((move_data[move].type == attacker.species.typenum1) || (move_data[move].type == attacker.species.typenum2)) &&
  402.       !((effect.flags & FLAG_IGNORE_STAB) || (global_flags & FLAG_NO_STAB))
  403.   ) power += power >> 1;
  404.   power += effect.add_offset * move_data[move].hit_chance; // add this AFTER calculating STAB!
  405.   if (power <= 0) return 0;
  406.   unsigned long long regular_damage, critical_damage;
  407.   regular_damage = critical_damage = (unsigned long long) attack_stat * power;
  408.   regular_damage *= 2 * attacker.level / 5 + 5;
  409.   critical_damage *= 4 * attacker.level / 5 + 5;
  410.   return critical_damage * crit_chance + regular_damage * (256 - crit_chance);
  411. }
  412.  
  413. unsigned calculate_transform_rating (Pokemon attacker) {
  414.   // will contain an implicit shift of 24
  415.   // treat it like a generic 80 base power, no effect, 99.6% accuracy STAB attack
  416.   // coming from a mon the same level as the attacker with 85 base all stats, 7 DVs, +32 @L100 from stat exp
  417.   unsigned long long base_power = 0x778800ULL * (5 + attacker.level * 54 / 25); // repeat the calculations above, but hardcode the values
  418.   unsigned long long regular_damage = base_power * (2 * attacker.level / 5 + 5);
  419.   unsigned long long critical_damage = base_power * (4 * attacker.level / 5 + 5);
  420.   return critical_damage * 42 + regular_damage * 214;
  421. }
  422.  
  423. void sort_pair (unsigned long long * lower, unsigned long long * higher) {
  424.   if (*lower <= *higher) return;
  425.   unsigned long long temp = *lower;
  426.   *lower = *higher;
  427.   *higher = temp;
  428. }
  429.  
  430. unsigned char count_moves_with_flag (Pokemon pkmn, unsigned short flag) {
  431.   unsigned char p, result = 0;
  432.   for (p = 0; p < 4; p ++) {
  433.     if (!pkmn.moves[p].id) continue;
  434.     if (get_move_flags(pkmn.moves[p].id) & flag) result ++;
  435.   }
  436.   return result;
  437. }
  438.  
  439. unsigned long long calculate_attacker_rating (Pokemon attacker) {
  440.   // will contain an implicit shift of 32
  441.   unsigned long long move_ratings[4];
  442.   unsigned char p, move_count = 0;
  443.   unsigned short flags;
  444.   for (p = 0; p < 4; p ++) {
  445.     if (!attacker.moves[p].id) continue;
  446.     flags = get_move_flags(attacker.moves[p].id);
  447.     if (flags & FLAG_IGNORE) continue;
  448.     move_ratings[move_count ++] = (flags & FLAG_TRANSFORM) ? calculate_transform_rating(attacker) : calculate_move_power_rating(attacker.moves[p].id, attacker);
  449.   }
  450.   if (!move_count) return 0;
  451.   // simple swap-based sort because there are only four entries anyway
  452.   switch (move_count) {
  453.     case 4:
  454.       sort_pair(move_ratings + 3, move_ratings);
  455.       sort_pair(move_ratings + 3, move_ratings + 1);
  456.       sort_pair(move_ratings + 3, move_ratings + 2);
  457.     case 3:
  458.       sort_pair(move_ratings + 2, move_ratings);
  459.       sort_pair(move_ratings + 2, move_ratings + 1);
  460.     case 2:
  461.       sort_pair(move_ratings + 1, move_ratings);
  462.   }
  463.   // weights: 9, 4, 2, 1. If the mon has less than four moves, the first move's weight is increased to keep the total at 16
  464.   unsigned long long weighted_total = *move_ratings << (4 - move_count);
  465.   for (p = 0; p < move_count; p ++) weighted_total += move_ratings[p] << (p ^ 3); // note that p ^ 3 is the same as 3 - p here
  466.   // take away 1/16 for every bad move the mon has
  467.   return weighted_total * (16 - count_moves_with_flag(attacker, FLAG_BAD_MOVE_CHOICE));
  468. }
  469.  
  470. unsigned long long calculate_defender_rating (Pokemon defender) {
  471.   // must contain an implicit shift of 32 to be compatible with calculate_attacker_rating
  472.   struct stats stats = calculate_stats(defender);
  473.   unsigned long long rating = stats.defense + stats.special_defense; // start with the good old stat average. Accumulated shift: 1
  474.   unsigned short low_stat = (stats.defense > stats.special_defense) ? stats.special_defense : stats.defense;
  475.   unsigned short high_stat = rating - low_stat; // simple trick here
  476.   rating *= stats.hp; // in two steps so there is no overflow
  477.   rating *= defender.species.base_stats.speed + 452; // offset of 1/512 for every base speed point away from 70. Accumulated shift: 10
  478.   rating *= 20; // adjustment factor: 50 for the damage formula, times 40% to make it equivalent to level
  479.   unsigned short stat_ratio = ((unsigned) low_stat << 16) / high_stat;
  480.   // factor in the stat spread, so mons like Chansey get their defensive rating lowered (because there is a weak point). Accumulated shift: 18
  481.   if ((stat_ratio > 65025) || !stat_ratio) // stat_ratio = 0 indicates low_stat = high_stat and some problematic overflow
  482.     rating <<= 8;
  483.   else
  484.     rating *= square_root(stat_ratio);
  485.   unsigned char total_moves = 0, dangerous_moves = 0, self_damaging_moves = 0;
  486.   struct move_effect_data effect;
  487.   unsigned char p;
  488.   for (p = 0; p < 4; p ++) {
  489.     if (!defender.moves[p].id) continue;
  490.     total_moves ++;
  491.     effect = get_move_effect_data(defender.moves[p].id);
  492.     if (effect.flags & FLAG_DANGEROUS) dangerous_moves ++;
  493.     if (effect.add_offset < 0) self_damaging_moves ++; // negative add mod means that the move hurts the user somehow
  494.   }
  495.   if ((total_moves == dangerous_moves) && (total_moves == self_damaging_moves)) return 0; // this mon is suicidal and should not be used at all
  496.   total_moves --; // easier indexing
  497.   rating *= 128 - dangerous_moves * total_moves[(unsigned char []) {128, 64, 43, 32}]; // dangerous move chance out of 128. Accumulated shift: 25
  498.   rating *= 128 - self_damaging_moves * total_moves[(unsigned char []) {60, 30, 20, 15}]; // 1 - (15/32 * self damage chance). Accumulated shift: 32
  499.   // nothing interesting to do here now
  500.   return rating;
  501. }
  502.  
  503. unsigned calculate_overall_rating (Pokemon pkmn) {
  504.   struct stats stats = calculate_stats(pkmn);
  505.   unsigned long long attack_rating = calculate_attacker_rating(pkmn), defense_rating = calculate_defender_rating(pkmn);
  506.   // faster mons attack first, hence the weights here. Note that they add a shift of 10
  507.   unsigned short attack_weight = (stats.speed * 100 / pkmn.level) + 320;
  508.   unsigned short defense_weight = 1024 - attack_weight;
  509.   // at this point we have to be very careful with overflows, so we split the values like this
  510.   unsigned long long attack_upper = attack_rating >> 32, attack_lower = attack_rating & 0xffffffffULL;
  511.   unsigned long long defense_upper = defense_rating >> 32, defense_lower = defense_rating & 0xffffffffULL;
  512.   attack_upper *= attack_weight;
  513.   attack_lower *= attack_weight;
  514.   defense_upper *= defense_weight;
  515.   defense_lower *= defense_weight;
  516.   unsigned long long rating = attack_upper + defense_upper, rating_lower = attack_lower + defense_lower;
  517.   rating += (rating_lower >> 32) + 512; // don't lose the carry from the lower bits before we discard them, and add 0x200 to round to nearest in the next step
  518.   return rating >> 10; // do away with all the shifts and return a rounded rating value
  519. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement