pokemon-showdown/test/sim/moves/futuresight.js

359 lines
13 KiB
JavaScript

'use strict';
const assert = require('./../../assert');
const common = require('./../../common');
let battle;
describe('Future Sight', function () {
afterEach(function () {
battle.destroy();
});
it(`should damage in two turns, ignoring Protect, affected by Dark immunities`, function () {
battle = common.createBattle([[
{species: 'Sneasel', moves: ['sleeptalk', 'futuresight']},
], [
{species: 'Girafarig', moves: ['sleeptalk', 'futuresight', 'protect']},
]]);
const sneasel = battle.p1.active[0];
const girafarig = battle.p2.active[0];
battle.makeChoices('move futuresight', 'move futuresight');
assert.fullHP(girafarig);
battle.makeChoices();
assert.fullHP(girafarig);
battle.makeChoices('auto', 'move protect');
assert.fullHP(sneasel);
assert.false.fullHP(girafarig);
});
it(`should fail when already active for the target's position`, function () {
battle = common.createBattle([[
{species: 'Sneasel', moves: ['sleeptalk']},
], [
{species: 'Girafarig', moves: ['futuresight']},
]]);
battle.makeChoices();
battle.makeChoices();
assert(battle.log[battle.lastMoveLine + 1].startsWith('|-fail|'));
});
it(`[Gen 2] should damage in two turns, ignoring Protect`, function () {
battle = common.gen(2).createBattle([[
{species: 'Sneasel', moves: ['sleeptalk', 'futuresight', 'sweetscent']},
], [
{species: 'Girafarig', moves: ['sleeptalk', 'futuresight', 'protect', 'sweetscent']},
]]);
const sneasel = battle.p1.active[0];
const girafarig = battle.p2.active[0];
battle.makeChoices('move sweetscent', 'move sweetscent'); // counteract imperfect accuracy
battle.makeChoices('move futuresight', 'move futuresight');
assert.fullHP(girafarig);
battle.makeChoices('auto', 'auto');
assert.fullHP(girafarig);
battle.makeChoices('auto', 'move Protect');
assert.false.fullHP(sneasel);
assert.false.fullHP(girafarig);
});
it(`should not double Stomping Tantrum for exiting normally`, function () {
battle = common.createBattle([[
{species: 'Wynaut', moves: ['futuresight', 'stompingtantrum']},
], [
{species: 'Scizor', ability: 'shellarmor', moves: ['sleeptalk']},
]]);
battle.makeChoices();
battle.makeChoices('move stompingtantrum', 'move sleeptalk');
const scizor = battle.p2.active[0];
const damage = scizor.maxhp - scizor.hp;
assert.bounded(damage, [19, 23]); // If it were doubled, would be 38-45
});
it(`should not trigger Eject Button`, function () {
battle = common.createBattle([[
{species: 'Wynaut', moves: ['futuresight']},
], [
{species: 'Scizor', item: 'ejectbutton', moves: ['sleeptalk']},
{species: 'Roggenrola', moves: ['sleeptalk']},
]]);
for (let i = 0; i < 3; i++) battle.makeChoices();
assert.equal(battle.requestState, 'move');
});
it(`should be able to set Future Sight against an empty target slot`, function () {
battle = common.createBattle([[
{species: 'Shedinja', moves: ['finalgambit']},
{species: 'Roggenrola', moves: ['sleeptalk']},
], [
{species: 'Wynaut', moves: ['sleeptalk', 'futuresight']},
]]);
battle.makeChoices('auto', 'move future sight');
battle.makeChoices('switch 2');
battle.makeChoices();
battle.makeChoices();
const roggenrola = battle.p1.active[0];
assert.false.fullHP(roggenrola);
});
it(`its damaging hit should not count as copyable for Copycat`, function () {
battle = common.createBattle([[
{species: 'Wynaut', moves: ['sleeptalk', 'futuresight']},
], [
{species: 'Liepard', moves: ['sleeptalk', 'copycat']},
]]);
battle.makeChoices('move futuresight', 'auto');
battle.makeChoices();
battle.makeChoices();
battle.makeChoices('auto', 'move copycat'); // Should fail due to last move being Sleep Talk
battle.makeChoices();
battle.makeChoices();
const wynaut = battle.p1.active[0];
assert.fullHP(wynaut);
});
it(`should only cause the user to take Life Orb recoil on its damaging turn`, function () {
battle = common.createBattle([[
{species: 'wynaut', item: 'lifeorb', moves: ['futuresight']},
], [
{species: 'mew', moves: ['sleeptalk']},
]]);
battle.makeChoices();
const wynaut = battle.p1.active[0];
const mew = battle.p2.active[0];
assert.fullHP(wynaut, `Wynaut should not take Life Orb recoil on Future Sight's starting turn`);
battle.makeChoices();
battle.makeChoices();
assert.equal(wynaut.hp, wynaut.maxhp - Math.floor(wynaut.maxhp / 10), `Wynaut should take Life Orb recoil on Future Sight's damaging turn`);
const damage = mew.maxhp - mew.hp;
assert.bounded(damage, [30, 35]); // 22-27 if Life Orb was not applied
});
it(`[Gen 4] should not be affected by Life Orb`, function () {
battle = common.gen(4).createBattle([[
{species: 'wynaut', item: 'lifeorb', moves: ['futuresight']},
], [
{species: 'mew', moves: ['sleeptalk']},
]]);
battle.makeChoices();
const wynaut = battle.p1.active[0];
const mew = battle.p2.active[0];
battle.makeChoices();
battle.makeChoices();
assert.fullHP(wynaut, `Wynaut should not have taken any damage`);
const damage = mew.maxhp - mew.hp;
assert.bounded(damage, [22, 27]); // 30, 35 if Life Orb was applied
});
it(`should not be affected by Life Orb if not the original user`, function () {
battle = common.createBattle([[
{species: 'wynaut', item: 'lifeorb', moves: ['futuresight']},
{species: 'liepard', item: 'lifeorb', moves: ['sleeptalk']},
], [
{species: 'mew', moves: ['sleeptalk']},
]]);
battle.makeChoices();
const liepard = battle.p1.pokemon[1];
const mew = battle.p2.active[0];
battle.makeChoices();
battle.makeChoices('switch 2', 'move sleeptalk');
assert.fullHP(liepard, `liepard should not have taken any damage`);
const damage = mew.maxhp - mew.hp;
assert.bounded(damage, [22, 27]); // 30, 35 if Life Orb was applied
});
it(`should not cause the user to change typing on either its starting or damaging turn`, function () {
battle = common.createBattle([[
{species: 'roggenrola', ability: 'protean', moves: ['futuresight', 'sleeptalk']},
], [
{species: 'mew', moves: ['sleeptalk']},
]]);
const roggenrola = battle.p1.active[0];
battle.makeChoices();
assert.false(roggenrola.hasType('Psychic'), `Protean Roggenrola should not change type on Future Sight's starting turn`);
battle.makeChoices();
battle.makeChoices();
assert.false(roggenrola.hasType('Psychic'), `Protean Roggenrola should not change type on Future Sight's damaging turn`);
});
it(`should be boosted by Terrain only if Terrain is active on the damaging turn`, function () {
battle = common.createBattle([[
{species: 'Blissey', ability: 'shellarmor', moves: ['softboiled']},
], [
{species: 'Wynaut', ability: 'psychicsurge', moves: ['sleeptalk', 'futuresight']},
]]);
battle.makeChoices('auto', 'move futuresight');
battle.makeChoices();
battle.makeChoices();
const blissey = battle.p1.active[0];
let damage = blissey.maxhp - blissey.hp;
assert.bounded(damage, [46, 55]);
battle.makeChoices('auto', 'move futuresight');
battle.makeChoices();
battle.makeChoices();
damage = blissey.maxhp - blissey.hp;
assert.bounded(damage, [36, 43]);
});
it(`should be boosted by Terrain even if the user is not on the field, as long as the user is not Flying-type`, function () {
battle = common.createBattle([[
{species: 'Blissey', ability: 'shellarmor', moves: ['softboiled']},
], [
{species: 'cresselia', ability: 'levitate', moves: ['sleeptalk', 'futuresight']},
{species: 'deino', ability: 'psychicsurge', moves: ['sleeptalk']},
{species: 'xatu', moves: ['sleeptalk', 'futuresight']},
]]);
// Cresselia will be Terrain-boosted because its Ability is not checked while not active
battle.makeChoices('auto', 'move futuresight');
battle.makeChoices();
battle.makeChoices('auto', 'switch deino');
const blissey = battle.p1.active[0];
let damage = blissey.maxhp - blissey.hp;
assert.bounded(damage, [102, 121]);
// Xatu won't be Terrain-boosted because its Flying-type is checked while not active
battle.makeChoices('auto', 'switch xatu');
battle.makeChoices('auto', 'move futuresight');
battle.makeChoices();
battle.makeChoices('auto', 'switch deino');
damage = blissey.maxhp - blissey.hp;
assert.bounded(damage, [96, 114]);
});
it(`should not ignore the target's screens, even when the user is not active on the field`, function () {
battle = common.createBattle([[
{species: 'Blissey', ability: 'shellarmor', item: 'lightclay', moves: ['softboiled', 'lightscreen']},
], [
{species: 'Wynaut', moves: ['sleeptalk', 'futuresight']},
{species: 'deino', moves: ['sleeptalk']},
]]);
battle.makeChoices('move lightscreen', 'move futuresight');
battle.makeChoices();
battle.makeChoices();
const blissey = battle.p1.active[0];
let damage = blissey.maxhp - blissey.hp;
assert.bounded(damage, [18, 21]);
battle.makeChoices('auto', 'move futuresight');
battle.makeChoices();
battle.makeChoices('auto', 'switch 2');
damage = blissey.maxhp - blissey.hp;
assert.bounded(damage, [18, 21]);
});
it(`should not consider the user's item or Ability when the user is not active`, function () {
battle = common.createBattle([[
{species: 'Blissey', ability: 'shellarmor', moves: ['softboiled']},
], [
{species: 'Wynaut', ability: 'adaptability', item: 'choicespecs', moves: ['futuresight']},
{species: 'Deino', ability: 'powerspot', moves: ['sleeptalk']},
]]);
for (let i = 0; i < 3; i++) battle.makeChoices();
const blissey = battle.p1.active[0];
let damage = blissey.maxhp - blissey.hp;
assert.bounded(damage, [70, 84]); // boosted by Adaptability and Choice Specs
battle.makeChoices();
battle.makeChoices();
battle.makeChoices('auto', 'switch 2');
damage = blissey.maxhp - blissey.hp;
assert.bounded(damage, [46, 55]); // only boosted by Power Spot
});
it(`should not ignore the target's Unaware`, function () {
battle = common.createBattle([[
{species: 'Manaphy', ability: 'simple', moves: ['tailglow', 'futuresight']},
], [
{species: 'Ho-Oh', ability: 'unaware', moves: ['luckychant']},
]]);
battle.makeChoices();
battle.makeChoices('move futuresight', 'auto');
battle.makeChoices();
battle.makeChoices();
const hooh = battle.p2.active[0];
const damage = hooh.maxhp - hooh.hp;
assert.bounded(damage, [60, 71]); // Damage would be 236-278 if Unaware was being ignored
});
it(`should use the user's most recent Special Attack stat if the user is on the field`, function () {
battle = common.createBattle([[
{species: 'Aegislash', ability: 'stancechange', moves: ['futuresight', 'kingsshield']},
], [
{species: 'Ho-Oh', ability: 'shellarmor', moves: ['recover']},
]]);
for (let i = 0; i < 3; i++) battle.makeChoices();
const hooh = battle.p2.active[0];
let damage = hooh.maxhp - hooh.hp;
assert.bounded(damage, [79, 94]); // Blade Forme damage
battle.makeChoices();
battle.makeChoices('move kingsshield', 'auto');
battle.makeChoices('move kingsshield', 'auto');
damage = hooh.maxhp - hooh.hp;
assert.bounded(damage, [34, 41]); // Shield Forme damage
});
it.skip(`should use the user's most recent Special Attack stat, even if the user is not on the field`, function () {
battle = common.createBattle([[
{species: 'Aegislash', ability: 'stancechange', moves: ['futuresight', 'kingsshield']},
{species: 'Wynaut', moves: ['sleeptalk']},
], [
{species: 'Ho-Oh', ability: 'shellarmor', moves: ['recover', 'flareblitz']},
]]);
battle.makeChoices();
battle.makeChoices('switch wynaut', 'auto');
battle.makeChoices();
const hooh = battle.p2.active[0];
let damage = hooh.maxhp - hooh.hp;
assert.bounded(damage, [79, 94], `Future Sight should deal Blade Forme damage, even though Aegislash switched out in Blade Forme`);
battle.makeChoices('switch aegislash', 'auto');
battle.makeChoices();
battle.makeChoices('auto', 'move flareblitz');
battle.makeChoices(); // switch in Wynaut
battle.makeChoices();
damage = hooh.maxhp - hooh.hp;
assert.bounded(damage, [79, 94], `Future Sight should deal Blade Forme damage, even though Aegislash was KOed in Blade Forme.`);
});
it(`should only use Sp. Atk stat boosts/drops if the user is on the field`, function () {
battle = common.createBattle([[
{species: 'Flapple', moves: ['futuresight', 'nastyplot', 'sleeptalk']},
{species: 'Wynaut', moves: ['sleeptalk']},
], [
{species: 'Ho-Oh', ability: 'shellarmor', moves: ['recover']},
]]);
battle.makeChoices();
battle.makeChoices('move nastyplot', 'auto');
battle.makeChoices();
const hooh = battle.p2.active[0];
let damage = hooh.maxhp - hooh.hp;
assert.bounded(damage, [113, 134], `Future Sight should deal damage with +2 Sp. Atk`);
battle.makeChoices();
battle.makeChoices('switch wynaut', 'auto');
battle.makeChoices();
damage = hooh.maxhp - hooh.hp;
assert.bounded(damage, [57, 68], `Future Sight should deal damage with +0 Sp. Atk`);
});
});