wartab

Hawlucha catch rate

Mar 25th, 2021 (edited)
538
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. let {calculate, Pokemon, Move} = require("@smogon/calc");
  2.  
  3. let karateChop = new Move(6, "Karate Chop");
  4. let wingAttack = new Move(6, "Wing Attack");
  5.  
  6. let karateChopCrit = new Move(6, "Karate Chop", {isCrit: true});
  7. let wingAttackCrit = new Move(6, "Wing Attack", {isCrit: true});
  8.  
  9. function randomInt(min, max) {
  10.     return Math.floor(Math.random() * (max - min + 1)) + min;
  11. }
  12.  
  13. function d(x) {
  14.     return Math.floor(x * 4096) / 4096;
  15. }
  16.  
  17. function r(x) {
  18.     return Math.round(x * 4096) / 4096;
  19. }
  20.  
  21. function tryHawluchaCatch(hp, maxHp) {
  22.     const catchRate = 100;
  23.  
  24.     let x = Math.min(255, d(r(d(r(r(3 * maxHp - 2 * hp) * catchRate) / (3 * maxHp)))));
  25.     let y;
  26.     if (x === 0) {
  27.         y = 0;
  28.     } else {
  29.         y = Math.floor(r(65536 / r(Math.pow(r(255 / x), 3 / 16))));
  30.     }
  31.  
  32.     let chance = Math.pow(y / 65536, 4);
  33.  
  34.     return Math.random() <= chance;
  35. }
  36.  
  37. function generateHawlucha(level) {
  38.     let hpIv = randomInt(0, 31);
  39.     let atkIv = randomInt(0, 31);
  40.     let defIv = randomInt(0, 31);
  41.  
  42.     let nature = randomInt(0, 24);
  43.     let natureName = "Serious";
  44.  
  45.     switch (nature) {
  46.         case 1: natureName = "Lonely"; break;
  47.         case 2: natureName = "Brave"; break;
  48.         case 3: natureName = "Adamant"; break;
  49.         case 4: natureName = "Naughty"; break;
  50.         case 5: natureName = "Bold"; break;
  51.         case 7: natureName = "Relaxed"; break;
  52.         case 8: natureName = "Impish"; break;
  53.         case 9: natureName = "Lax"; break;
  54.         case 10: natureName = "Timid"; break;
  55.         case 11: natureName = "Hasty"; break;
  56.         case 15: natureName = "Modest"; break;
  57.         case 16: natureName = "Mild"; break;
  58.         case 20: natureName = "Calm"; break;
  59.         case 21: natureName = "Gentle"; break;
  60.     }
  61.  
  62.     let pokemon = new Pokemon(6, "Hawlucha", {
  63.         ivs: {hp: hpIv, atk: atkIv, def: defIv, spa: 0, spd: 0, spe: 0},
  64.         nature: natureName,
  65.         level: level,
  66.     });
  67.  
  68.     return {
  69.         maxHp: pokemon.rawStats.hp,
  70.         hp: pokemon.rawStats.hp,
  71.         pokemon: pokemon,
  72.         hasKingsRock: randomInt(0, 19) === 0,
  73.     };
  74. }
  75.  
  76. function simulateEncounter(useAerialAce, hp, atk, def, level) {
  77.  
  78.     let ballsLeft = 3;
  79.  
  80.     let hawlucha = generateHawlucha(level);
  81.     let _hawlucha = hawlucha.pokemon;
  82.  
  83.     // if (hawlucha.hasKingsRock) {
  84.     //     console.log("Hawlucha has King's Rock.");
  85.     // }
  86.  
  87.     let _farfetchd = new Pokemon(6, "Farfetch'd", {
  88.         ivs: {hp: hp, atk: atk, def: def, spa: 0, spd: 0, spe: 0},
  89.         evs: {hp: 2, atk: 4, def: 3, spa: 3, spd: 1, spe: 9},
  90.         nature: "Jolly",
  91.         level: 18,
  92.     });
  93.  
  94.     let farfetchd = {
  95.         maxHp: _farfetchd.rawStats.hp,
  96.         hp: _farfetchd.rawStats.hp,
  97.         pokemon: _farfetchd,
  98.     }
  99.  
  100.     for (let turn = 1;; ++turn) {
  101.         // console.log("");
  102.         // console.log("Turn " + turn);
  103.  
  104.  
  105.         let hawluchaMove = randomInt(0, 3);
  106.  
  107.         let damageRolls = null;
  108.  
  109.         let tryBallThrow = !(useAerialAce && hawlucha.maxHp * 0.8 <= hawlucha.hp && farfetchd.maxHp === farfetchd.hp);
  110.  
  111.         if (tryBallThrow) {
  112.             let catchSuccess = tryHawluchaCatch(hawlucha.hp, hawlucha.maxHp);
  113.  
  114.             --ballsLeft;
  115.  
  116.             if (!catchSuccess) {
  117.                 // console.log("Failed catch: " + ballsLeft +  " balls left.");
  118.  
  119.                 if (ballsLeft === 0) {
  120.                     return {
  121.                         success: false,
  122.                         turn: turn,
  123.                         result: "out of balls",
  124.                     };
  125.                 }
  126.             } else {
  127.                 // console.log("Succeeded catch: " + ballsLeft +  " balls left.");
  128.  
  129.                 return {
  130.                     success: true,
  131.                     turn: turn,
  132.                 };
  133.             }
  134.         }
  135.  
  136.         if (level === 19) {
  137.             switch (hawluchaMove) {
  138.                 case 0: { // Karate Chop
  139.  
  140.                     let crit = randomInt(0, 7) === 0;
  141.  
  142.                     damageRolls = calculate(6, _hawlucha, _farfetchd, crit ? karateChopCrit : karateChop).damage;
  143.  
  144.                     break;
  145.                 }
  146.                 case 1:
  147.                 case 3: { // Aerial Ace, Wing Attack
  148.  
  149.                     let crit = randomInt(0, 15) === 0;
  150.  
  151.                     damageRolls = calculate(6, _hawlucha, _farfetchd, crit ? wingAttackCrit : wingAttack).damage;
  152.  
  153.                     break;
  154.                 }
  155.  
  156.                 case 2: { // Roost
  157.                     // console.log("Hawlucha used Roost.");
  158.                     hawlucha.hp = Math.min(hawlucha.maxHp, hawlucha.hp + Math.floor(hawlucha.maxHp / 2));
  159.                     break;
  160.                 }
  161.             }
  162.         } else {
  163.             switch (hawluchaMove) {
  164.                 case 0:
  165.                 case 2: { // Aerial Ace, Wing Attack
  166.  
  167.                     let crit = randomInt(0, 15) === 0;
  168.  
  169.                     damageRolls = calculate(6, _hawlucha, _farfetchd, crit ? wingAttackCrit : wingAttack).damage;
  170.  
  171.                     break;
  172.                 }
  173.  
  174.                 case 1: { // Roost
  175.                     // console.log("Hawlucha used Roost.");
  176.                     hawlucha.hp = Math.min(hawlucha.maxHp, hawlucha.hp + Math.floor(hawlucha.maxHp / 2));
  177.                     break;
  178.                 }
  179.                 case 3: // Encore, do nothing
  180.                     // console.log("Hawlucha used Encore.");
  181.                     break;
  182.             }
  183.         }
  184.  
  185.         if (damageRolls !== null) {
  186.  
  187.             let damage = damageRolls[randomInt(0, 15)];
  188.  
  189.             // console.log("Farfetch'd took " + damage + " damage.");
  190.  
  191.             farfetchd.hp -= damage;
  192.  
  193.             // console.log("Farfetch'd has " + farfetchd.hp + " HP.");
  194.  
  195.             if (farfetchd.hp <= 0) {
  196.                 return {
  197.                     success: false,
  198.                     turn: turn,
  199.                     result: "farfetchd fainted",
  200.                 };
  201.             }
  202.         }
  203.  
  204.         if (!tryBallThrow) {
  205.             // console.log("Farfetch'd used Aerial Ace");
  206.  
  207.             if (hawlucha.hasKingsRock && damageRolls !== null && randomInt(0, 9) === 0) {
  208.                 // console.log("Farfetch'd flinched");
  209.                 continue;
  210.             }
  211.  
  212.             let crit = randomInt(0, 15) === 0;
  213.             damageRolls = calculate(6, _farfetchd, _hawlucha, crit ? wingAttackCrit : wingAttack).damage;
  214.             let damage = damageRolls[randomInt(0, 15)];
  215.  
  216.             hawlucha.hp -= damage;
  217.  
  218.             // console.log("Hawlucha has " + hawlucha.hp + " left (damage taken: " + damage + ").");
  219.  
  220.  
  221.             if (hawlucha.hp <= 0) {
  222.                 // Should almost never happen, can happen with lowest Defense & HP & crit and is at best a 5 / 16 range.
  223.  
  224.                 return {
  225.                     success: false,
  226.                     turn: turn,
  227.                     result: "hawlucha fainted",
  228.                 };
  229.             }
  230.         }
  231.     }
  232. }
  233.  
  234.  
  235. for (let level = 19; level <= 20; ++level) {
  236.  
  237.     for (let iv = 0; iv <=1; ++iv) {
  238.         for (let ae = 0; ae <= 1; ++ae) {
  239.             let successCounter = 0;
  240.             let successTurns = 0;
  241.  
  242.             let ivs = iv === 0 ? 0 : 31;
  243.  
  244.             for (let i = 0; i < 1000000; ++i) {
  245.                 let result = simulateEncounter(!!ae, ivs, ivs, ivs, level);
  246.  
  247.                 if (result.success) {
  248.                     ++successCounter;
  249.                     successTurns += result.turn;
  250.                 }
  251.             }
  252.  
  253.             console.log("");
  254.             console.log("Level: " + level);
  255.             console.log("IVs: " + ivs);
  256.             console.log("Aerial Ace: " + ae.toString());
  257.             console.log((successCounter / 10000).toFixed(2));
  258.             console.log("Turns: " + (successTurns / successCounter).toFixed(2));
  259.         }
  260.     }
  261. }
  262.  
Advertisement
Add Comment
Please, Sign In to add comment