Spaces:
Sleeping
Sleeping
; | |
const assert = require('./../../assert'); | |
const common = require('./../../common'); | |
let battle; | |
describe('Future Sight', () => { | |
afterEach(() => { | |
battle.destroy(); | |
}); | |
it(`should damage in two turns, ignoring Protect, affected by Dark immunities`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
battle = common.gen(4).createBattle([[ | |
{ species: 'wynaut', item: 'lifeorb', moves: ['futuresight'] }, | |
], [ | |
{ species: 'mew', ability: 'noguard', 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, [21, 25]); // [27-32] if Life Orb was applied | |
}); | |
it(`should not be affected by Life Orb if not the original user`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
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`, () => { | |
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`); | |
}); | |
it(`should never resolve when used on turn 254 or later`, () => { | |
battle = common.createBattle([[ | |
{ species: 'Wynaut', moves: ['sleeptalk', 'futuresight'] }, | |
], [ | |
{ species: 'Stakataka', moves: ['sleeptalk'] }, | |
]]); | |
battle.turn = 255; // Showdown turn is +1 from what the games are; this would ordinarily be 254 | |
battle.makeChoices('move futuresight', 'auto'); | |
for (let i = 0; i < 5; i++) battle.makeChoices(); | |
battle.makeChoices('move futuresight', 'auto'); | |
for (let i = 0; i < 5; i++) battle.makeChoices(); | |
const stak = battle.p2.active[0]; | |
assert.fullHP(stak, `Future Sight should have never resolved.`); | |
}); | |
it(`should target particular slots in Doubles`, () => { | |
battle = common.createBattle({ gameType: 'doubles' }, [[ | |
{ species: 'Wynaut', moves: ['sleeptalk', 'futuresight'] }, | |
{ species: 'Steelix', moves: ['sleeptalk'] }, | |
], [ | |
{ species: 'Girafarig', moves: ['sleeptalk', 'recover'] }, | |
{ species: 'Farigiraf', moves: ['sleeptalk', 'recover'] }, | |
]]); | |
battle.makeChoices('move futuresight 2, auto', 'auto'); | |
battle.makeChoices(); | |
battle.makeChoices(); | |
const giraf = battle.p2.active[0]; | |
const farig = battle.p2.active[1]; | |
assert.false.fullHP(farig, `Farigiraf should have been damaged by the 1st Future Sight.`); | |
battle.makeChoices('move futuresight 1, auto', 'move recover, move recover'); | |
battle.makeChoices(); | |
battle.makeChoices(); | |
assert.false.fullHP(giraf, `Girafarig should have been damaged by the 2nd Future Sight.`); | |
battle.makeChoices('move futuresight -2, auto', 'auto'); | |
battle.makeChoices(); | |
battle.makeChoices(); | |
const steelix = battle.p1.active[1]; | |
assert.false.fullHP(steelix, `Steelix should have been damaged by the 3rd Future Sight`); | |
}); | |
it(`should do nothing if no Pokemon is present to take damage from the Future attack`, () => { | |
battle = common.createBattle([[ | |
{ species: 'Wynaut', ability: 'magicguard', moves: ['sleeptalk'] }, | |
{ species: 'Shedinja', moves: ['sleeptalk'] }, | |
], [ | |
{ species: 'Happiny', moves: ['stealthrock', 'futuresight'] }, | |
]]); | |
battle.makeChoices('auto', 'move futuresight'); | |
battle.makeChoices('auto', 'move stealthrock'); | |
battle.makeChoices('switch 2', 'auto'); | |
battle.makeChoices('switch 2'); | |
battle.makeChoices(); | |
const wynaut = battle.p1.active[0]; | |
assert.fullHP(wynaut); | |
}); | |
}); | |