{Attachment, Status} = require('../../server/xy/attachment') {Battle} = require('../../server/xy/battle') {Pokemon} = require('../../server/xy/pokemon') {Weather} = require('../../shared/weather') {Move} = require('../../server/xy/move') util = require '../../server/xy/util' {Protocol} = require '../../shared/protocol' {Factory} = require '../factory' should = require 'should' {_} = require 'underscore' shared = require '../shared' require '../helpers' describe "XY Moves:", -> # Test every single move for their primary effects. shared.testEveryMove(Battle::MoveList, 'xy') describe "a critical hit", -> it "multiplies damage by 1.5x", -> Move::criticalMultiplier.should.equal(1.5) it "becomes a 50% chance at a +3 CH level", -> Move::determineCriticalHitFromLevel(3, .49).should.be.true Move::determineCriticalHitFromLevel(3, .5).should.be.false it "becomes a 100% chance at a +4 CH level", -> Move::determineCriticalHitFromLevel(4, .99).should.be.true Move::determineCriticalHitFromLevel(4, 1.0).should.be.false describe "a powder move", -> it "does not affect Grass-types", -> shared.create.call(this, gen: 'xy') powderMove = @battle.findMove((m) -> m.hasFlag("powder")) @p2.types.push("Grass") mock1 = @sandbox.mock(powderMove).expects('hit').never() mock2 = @sandbox.mock(powderMove).expects('fail').once() @battle.performMove(@p1, powderMove) mock1.verify() mock2.verify() it "affects non-Grass-types", -> shared.create.call(this, gen: 'xy') powderMove = @battle.findMove((m) -> m.hasFlag("powder")) @p2.types = [ "Normal" ] mock1 = @sandbox.mock(powderMove).expects('hit').once() mock2 = @sandbox.mock(powderMove).expects('fail').never() @battle.performMove(@p1, powderMove) mock1.verify() mock2.verify() describe "Dragon Pulse", -> it "has 85 base power now", -> shared.create.call(this, gen: 'xy') @battle.getMove('Dragon Pulse').power.should.equal(85) describe 'Hidden Power', -> it "always has 60 base power", -> shared.create.call(this, gen: 'xy') hiddenPower = @battle.getMove('Hidden Power') hiddenPower.power.should.equal(60) hiddenPower.basePower(@battle, @p1, @p2).should.equal(60) describe "Facade", -> it "does not cut attack in half when burned", -> shared.create.call(this, gen: 'xy') facade = @battle.getMove('Facade') facade.burnCalculation(@p1).should.equal(1) @p1.attach(Status.Burn) facade.burnCalculation(@p1).should.equal(1) describe "King's Shield", -> it "protects against attacks", -> shared.create.call(this, gen: 'xy') kingsShield = @battle.getMove("King's Shield") tackle = @battle.getMove("Tackle") mock = @sandbox.mock(tackle).expects('hit').never() @battle.recordMove(@id2, tackle) @battle.determineTurnOrder() @battle.performMove(@p1, kingsShield) @battle.performMove(@p2, tackle) mock.verify() it "does not protect against non-damaging moves", -> shared.create.call(this, gen: 'xy') kingsShield = @battle.getMove("King's Shield") willOWisp = @battle.getMove("Will-O-Wisp") mock = @sandbox.mock(willOWisp).expects('hit').once() @battle.recordMove(@id2, willOWisp) @battle.determineTurnOrder() @battle.performMove(@p1, kingsShield) @battle.performMove(@p2, willOWisp) mock.verify() it "does not protect against attacks it is immune to", -> shared.create.call(this, gen: 'xy') @p1.types = [ 'Ghost' ] kingsShield = @battle.getMove("King's Shield") tackle = @battle.getMove("Tackle") mock = @sandbox.mock(tackle).expects('hit').never() @battle.recordMove(@id2, tackle) @battle.determineTurnOrder() @battle.performMove(@p1, kingsShield) @battle.performMove(@p2, tackle) mock.verify() @p2.stages.should.containEql(attack: 0) it "sharply lowers attacker's Attack if move was a contact move", -> shared.create.call(this, gen: 'xy') kingsShield = @battle.getMove("King's Shield") tackle = @battle.getMove("Tackle") @battle.recordMove(@id2, tackle) @battle.determineTurnOrder() @battle.performMove(@p1, kingsShield) @p2.stages.attack.should.equal(0) @battle.performMove(@p2, tackle) @p2.stages.attack.should.equal(-2) it "does not lower attacker's Attack if move was not a contact move", -> shared.create.call(this, gen: 'xy') kingsShield = @battle.getMove("King's Shield") ember = @battle.getMove("Ember") @battle.recordMove(@id2, ember) @battle.determineTurnOrder() @battle.performMove(@p1, kingsShield) @p2.stages.attack.should.equal(0) @battle.performMove(@p2, ember) @p2.stages.attack.should.equal(0) describe "Spiky Shield", -> it "protects against attacks", -> shared.create.call(this, gen: 'xy') spikyShield = @battle.getMove("Spiky Shield") tackle = @battle.getMove("Tackle") mock = @sandbox.mock(tackle).expects('hit').never() @battle.recordMove(@id2, tackle) @battle.determineTurnOrder() @battle.performMove(@p1, spikyShield) @battle.performMove(@p2, tackle) mock.verify() it "protects against non-damaging moves", -> shared.create.call(this, gen: 'xy') spikyShield = @battle.getMove("Spiky Shield") willOWisp = @battle.getMove("Will-O-Wisp") mock = @sandbox.mock(willOWisp).expects('hit').never() @battle.recordMove(@id2, willOWisp) @battle.determineTurnOrder() @battle.performMove(@p1, spikyShield) @battle.performMove(@p2, willOWisp) mock.verify() it "does not protect against attacks it is immune to", -> shared.create.call(this, gen: 'xy') @p1.types = [ 'Ghost' ] spikyShield = @battle.getMove("Spiky Shield") tackle = @battle.getMove("Tackle") mock = @sandbox.mock(tackle).expects('hit').never() @battle.recordMove(@id2, tackle) @battle.determineTurnOrder() @battle.performMove(@p1, spikyShield) @battle.performMove(@p2, tackle) mock.verify() @p2.stages.should.containEql(attack: 0) it "damages attacker by 1/8 if move was a contact move", -> shared.create.call(this, gen: 'xy') spikyShield = @battle.getMove("Spiky Shield") tackle = @battle.getMove("Tackle") @battle.recordMove(@id2, tackle) @battle.determineTurnOrder() @battle.performMove(@p1, spikyShield) @p2.currentHP.should.not.be.lessThan(@p2.stat('hp')) @battle.performMove(@p2, tackle) (@p2.stat('hp') - @p2.currentHP).should.equal(@p2.stat('hp') >> 3) it "does not damage attacker if move was not a contact move", -> shared.create.call(this, gen: 'xy') spikyShield = @battle.getMove("Spiky Shield") ember = @battle.getMove("Ember") @battle.recordMove(@id2, ember) @battle.determineTurnOrder() @battle.performMove(@p1, spikyShield) @p2.currentHP.should.not.be.lessThan(@p2.stat('hp')) @battle.performMove(@p2, ember) @p2.currentHP.should.not.be.lessThan(@p2.stat('hp')) describe "Sticky Web", -> shared.shouldFailIfUsedTwice("Sticky Web", gen: 'xy') it "lowers a pokemon's speed by 1 when switching in", -> shared.create.call(this, gen: 'xy', team2: (Factory("Magikarp") for x in [0..1])) stickyWeb = @battle.getMove("Sticky Web") @battle.performMove(@p1, stickyWeb) @battle.performSwitch(@p2, 1) @team2.first().stages.should.containEql(speed: -1) it "doesn't lower a pokemon's speed by 1 if immune to ground", -> shared.create.call(this, gen: 'xy', team2: [ Factory("Magikarp"), Factory("Gyarados") ]) stickyWeb = @battle.getMove("Sticky Web") @battle.performMove(@p1, stickyWeb) @battle.performSwitch(@p2, 1) @team2.first().stages.should.containEql(speed: 0) describe "Rapid Spin", -> it "removes Sticky Web", -> shared.create.call(this, gen: 'xy') stickyWeb = @battle.getMove("Sticky Web") rapidSpin = @battle.getMove("Rapid Spin") @battle.performMove(@p1, stickyWeb) @team2.has(Attachment.StickyWeb).should.be.true @battle.performMove(@p2, rapidSpin) @team2.has(Attachment.StickyWeb).should.be.false describe "Defog", -> it "removes Sticky Web as well", -> shared.create.call(this, gen: 'xy') defog = @battle.getMove("Defog") @battle.performMove(@p1, @battle.getMove("Sticky Web")) @p2.team.has(Attachment.StickyWeb).should.be.true @battle.performMove(@p1, defog) @p2.team.has(Attachment.StickyWeb).should.be.false it "removes hazards from both sides of the field now", -> shared.create.call(this, gen: 'xy') defog = @battle.getMove("Defog") @battle.performMove(@p1, @battle.getMove("Sticky Web")) @battle.performMove(@p2, @battle.getMove("Sticky Web")) @p1.team.has(Attachment.StickyWeb).should.be.true @p2.team.has(Attachment.StickyWeb).should.be.true @battle.performMove(@p1, defog) @p1.team.has(Attachment.StickyWeb).should.be.false @p2.team.has(Attachment.StickyWeb).should.be.false it "removes screens from only the target's side of the field", -> shared.create.call(this, gen: 'xy') defog = @battle.getMove("Defog") @battle.performMove(@p1, @battle.getMove("Reflect")) @battle.performMove(@p1, @battle.getMove("Light Screen")) @battle.performMove(@p2, @battle.getMove("Reflect")) @battle.performMove(@p2, @battle.getMove("Light Screen")) @p1.team.has(Attachment.Reflect).should.be.true @p1.team.has(Attachment.LightScreen).should.be.true @p2.team.has(Attachment.Reflect).should.be.true @p2.team.has(Attachment.LightScreen).should.be.true @battle.performMove(@p1, defog) @p1.team.has(Attachment.Reflect).should.be.true @p1.team.has(Attachment.LightScreen).should.be.true @p2.team.has(Attachment.Reflect).should.be.false @p2.team.has(Attachment.LightScreen).should.be.false describe "Knock Off", -> it "has x1.0 power if the pokemon has no item", -> shared.create.call(this, gen: 'xy') knockOff = @battle.getMove("Knock Off") knockOff.basePower(@battle, @p1, @p2).should.equal(knockOff.power) it "has x1.5 power if the item can be knocked off", -> shared.create.call this, gen: 'xy' team2: [Factory("Magikarp", item: "Leftovers")] knockOff = @battle.getMove("Knock Off") basePower = knockOff.basePower(@battle, @p1, @p2) basePower.should.equal Math.floor(1.5 * knockOff.power) it "has x1.0 power if the item cannot be knocked off", -> shared.create.call this, gen: 'xy' team2: [Factory("Magikarp", item: "Air Mail")] knockOff = @battle.getMove("Knock Off") knockOff.basePower(@battle, @p1, @p2).should.equal(knockOff.power) it "has x1.5 power if item can be knocked off but owner has Sticky Hold", -> shared.create.call this, gen: 'xy' team2: [Factory("Magikarp", item: "Leftovers", ability: "Sticky Hold")] knockOff = @battle.getMove("Knock Off") basePower = knockOff.basePower(@battle, @p1, @p2) basePower.should.equal Math.floor(1.5 * knockOff.power) describe "Protect-like moves", -> it "determines success chance using a power of 3 instead of 2", -> shared.create.call(this, gen: 'xy') for x in [0..7] attachment = @p1.attach(Attachment.ProtectCounter) attachment.successChance().should.equal Math.pow(3, x) attachment = @p1.attach(Attachment.ProtectCounter) attachment.successChance().should.equal Math.pow(2, 32) describe "Freeze-Dry", -> it "is 2x effective against Water-types", -> shared.create.call(this, gen: 'xy') @p2.types = [ "Water" ] freezeDry = @battle.getMove('Freeze-Dry') spy = @sandbox.spy(freezeDry, 'typeEffectiveness') @battle.performMove(@p1, freezeDry) spy.returned(2).should.be.true it "is 2x effective against Water-types with Normalize", -> shared.create.call this, gen: 'xy' team1: [Factory("Magikarp", ability: "Normalize")] @p2.types = [ "Water" ] freezeDry = @battle.getMove('Freeze-Dry') spy = @sandbox.spy(freezeDry, 'typeEffectiveness') @battle.performMove(@p1, freezeDry) spy.returned(2).should.be.true it "is normally effective against other types", -> shared.create.call this, gen: 'xy' team1: [Factory("Magikarp")] @p2.types = [ "Fire" ] freezeDry = @battle.getMove('Freeze-Dry') spy = @sandbox.spy(freezeDry, 'typeEffectiveness') @battle.performMove(@p1, freezeDry) spy.returned(.5).should.be.true describe "Substitute", -> it "is bypassed by voice moves", -> shared.create.call(this, gen: 'xy') @p2.attach(Attachment.Substitute, hp: (@p1.currentHP >> 2)) voiceMove = @battle.findMove (m) -> !m.isNonDamaging() && m.hasFlag("sound") spy = @sandbox.spy(voiceMove, 'hit') @battle.performMove(@p1, voiceMove) spy.calledOnce.should.be.true @p2.currentHP.should.be.lessThan(@p2.stat('hp')) it "is bypassed by Infiltrator", -> shared.create.call this, gen: 'xy' team1: [ Factory("Magikarp", ability: "Infiltrator")] @p2.attach(Attachment.Substitute, hp: (@p1.currentHP >> 2)) tackle = @battle.getMove("Tackle") spy = @sandbox.spy(tackle, 'hit') @battle.performMove(@p1, tackle) spy.calledOnce.should.be.true @p2.currentHP.should.be.lessThan(@p2.stat('hp')) it "is bypassed by Infiltrator even on status moves", -> shared.create.call this, gen: 'xy' team1: [ Factory("Magikarp", ability: "Infiltrator")] @p2.attach(Attachment.Substitute, hp: (@p1.currentHP >> 2)) toxic = @battle.getMove("Toxic") spy = @sandbox.spy(toxic, 'hit') @battle.performMove(@p1, toxic) spy.calledOnce.should.be.true @p2.has(Status.Toxic).should.be.true it "does not block Knock Off + Infiltrator", -> shared.create.call this, gen: 'xy' team1: [ Factory("Magikarp", ability: "Infiltrator")] team2: [ Factory("Magikarp", item: "Leftovers")] @p2.attach(Attachment.Substitute, hp: (@p1.currentHP >> 2)) knockOff = @battle.getMove("Knock Off") spy = @sandbox.spy(knockOff, 'hit') @battle.performMove(@p1, knockOff) spy.calledOnce.should.be.true @p2.hasItem().should.be.false it "does not block secondary effects + Infiltrator", -> shared.create.call this, gen: 'xy' team1: [ Factory("Magikarp", ability: "Infiltrator")] shared.biasRNG.call(this, "next", "secondary effect", 0) # always burn @p2.attach(Attachment.Substitute, hp: (@p1.currentHP >> 2)) flamethrower = @battle.getMove('Flamethrower') spy = @sandbox.spy(flamethrower, 'hit') @battle.performMove(@p1, flamethrower) spy.calledOnce.should.be.true @p2.has(Status.Burn).should.be.true testChargeMove = (moveName, vulnerable) -> describe moveName, -> it "chooses the player's next action for them", -> shared.create.call(this, gen: 'xy') move = @battle.getMove(moveName) @p1.moves = [ move ] @battle.recordMove(@id1, move) @battle.continueTurn() @battle.endTurn() @battle.beginTurn() @battle.requests.should.not.have.property(@id1) should.exist(@battle.getAction(@p1)) it "only spends 1 PP for the entire attack", -> shared.create.call(this, gen: 'xy') move = @battle.getMove(moveName) @p1.moves = [ move ] @p1.resetAllPP() pp = @p1.pp(move) @battle.recordMove(@id1, move) @battle.continueTurn() @p1.pp(move).should.equal(pp) @battle.beginTurn() @battle.continueTurn() @p1.pp(move).should.equal(pp - 1) it "skips the charge turn if the user is holding a Power Herb", -> shared.create.call this, gen: 'xy' team1: [Factory("Magikarp", item: "Power Herb")] move = @battle.getMove(moveName) @p1.hasItem("Power Herb").should.be.true mock = @sandbox.mock(move).expects('execute').once() @battle.recordMove(@id1, move) @battle.continueTurn() mock.verify() @p1.hasItem().should.be.false if vulnerable?.length? it "makes target invulnerable to moves", -> shared.create.call this, gen: 'xy' team1: [Factory("Magikarp", evs: {speed: 4})] move = @battle.getMove(moveName) swift = @battle.getMove("Swift") @battle.recordMove(@id1, move) @battle.recordMove(@id2, swift) mock = @sandbox.mock(swift).expects('hit').never() @battle.continueTurn() mock.verify() it "makes target invulnerable to moves *after* use", -> shared.create.call this, gen: 'xy' team2: [Factory("Magikarp", evs: {speed: 4})] move = @battle.getMove(moveName) tackle = @battle.getMove("Tackle") @battle.recordMove(@id1, move) @battle.recordMove(@id2, tackle) mock = @sandbox.mock(tackle).expects('hit').once() @battle.continueTurn() mock.verify() it "is vulnerable to attacks from a No Guard pokemon", -> shared.create.call this, gen: 'xy' team2: [Factory("Magikarp", ability: "No Guard")] move = @battle.getMove(moveName) tackle = @battle.getMove("Tackle") @battle.recordMove(@id1, move) @battle.recordMove(@id2, tackle) mock = @sandbox.mock(tackle).expects('hit').once() @battle.continueTurn() mock.verify() it "is vulnerable to attacks if locked on", -> shared.create.call(this, gen: 'xy') @battle.performMove(@p1, @battle.getMove("Lock-On")) @battle.performMove(@p2, @battle.getMove(moveName)) tackle = @battle.getMove("Tackle") @battle.recordMove(@id1, tackle) mock = @sandbox.mock(tackle).expects('hit').once() @battle.continueTurn() mock.verify() for vulnerableMove in vulnerable it "is vulnerable to #{vulnerableMove}", -> shared.create.call this, gen: 'xy' team1: [Factory("Magikarp", evs: {speed: 4})] move = @battle.getMove(moveName) vulnerable = @battle.getMove(vulnerableMove) @battle.recordMove(@id1, move) @battle.recordMove(@id2, vulnerable) mock = @sandbox.mock(vulnerable).expects('hit').once() @battle.continueTurn() mock.verify() else # no vulnerable moves it "doesn't make target invulnerable to moves", -> shared.create.call this, gen: 'xy' team1: [Factory("Magikarp", evs: {speed: 4})] move = @battle.getMove(moveName) tackle = @battle.getMove("Tackle") @battle.recordMove(@id1, move) @battle.recordMove(@id2, tackle) mock = @sandbox.mock(tackle).expects('hit').once() @battle.continueTurn() mock.verify() testChargeMove('Fly', ["Gust", "Thunder", "Twister", "Sky Uppercut", "Hurricane", "Smack Down", "Thousand Arrows"]) testChargeMove('Bounce', ["Gust", "Thunder", "Twister", "Sky Uppercut", "Hurricane", "Smack Down", "Thousand Arrows"]) testChargeMove('Geomancy') testChargeMove('Phantom Force', []) describe "Toxic", -> it "cannot miss when used by a Poison type pokemon", -> shared.create.call(this, gen: 'xy') @p1.types = [ "Poison" ] @p2.types = [ "Normal" ] shared.biasRNG.call(this, "randInt", 'miss', 101) toxic = @battle.getMove("Toxic") toxic.willMiss(@battle, @p1, @p2).should.be.false describe "Parting Shot", -> it "reduces the attack and special attack of the target by two stages", -> shared.create.call(this, gen: 'xy') @battle.performMove(@p1, @battle.getMove("Parting Shot")) @p2.stages.should.containEql attack: -1, specialAttack: -1 it "forces the owner to switch", -> shared.create.call(this, gen: 'xy') @battle.performMove(@p1, @battle.getMove("Parting Shot")) @battle.requests.should.have.property @id1 describe "Worry Seed", -> it "does not change some abilities", -> shared.create.call this, gen: 'xy' team1: [Factory("Smeargle")] team2: [Factory("Aegislash", ability: "Stance Change")] worrySeed = @battle.getMove("Worry Seed") mock = @sandbox.mock(worrySeed).expects('fail').once() @battle.performMove(@p1, worrySeed) mock.verify() describe "Simple Beam", -> it "does not change some abilities", -> shared.create.call this, gen: 'xy' team1: [Factory("Smeargle")] team2: [Factory("Aegislash", ability: "Stance Change")] simpleBeam = @battle.getMove("Simple Beam") mock = @sandbox.mock(simpleBeam).expects('fail').once() @battle.performMove(@p1, simpleBeam) mock.verify() testTrappingMove = (name) -> describe name, -> it "deals 1/8 of the pokemon's max hp every turn", -> shared.create.call this, gen: 'xy' team2: [Factory("Blissey")] @battle.performMove(@p1, @battle.getMove(name)) @p2.currentHP = @p2.stat('hp') @battle.endTurn() maxHP = @p2.stat('hp') expected = maxHP - Math.floor(maxHP / 8) @p2.currentHP.should.equal expected it "deals 1/6 of the pokemon's max hp every turn if the user is holding a Binding Band", -> shared.create.call this, gen: 'xy' team1: [Factory("Magikarp", item: "Binding Band")] team2: [Factory("Blissey")] @battle.performMove(@p1, @battle.getMove(name)) @p2.currentHP = @p2.stat('hp') @battle.endTurn() maxHP = @p2.stat('hp') expected = maxHP - Math.floor(maxHP / 6) @p2.currentHP.should.equal expected testTrappingMove "Bind" testTrappingMove "Clamp" testTrappingMove "Fire Spin" testTrappingMove "Infestation" testTrappingMove "Magma Storm" testTrappingMove "Sand Tomb" testTrappingMove "Wrap" describe "Entrainment", -> it "does not change some abilities", -> shared.create.call this, gen: 'xy' team1: [Factory("Magikarp", ability: "Swift Swim")] team2: [Factory("Aegislash", ability: "Stance Change")] entrainment = @battle.getMove("Entrainment") mock = @sandbox.mock(entrainment).expects('fail').once() @battle.performMove(@p1, entrainment) mock.verify() describe "Nature Power", -> it "uses Tri Attack in Wi-Fi battles", -> shared.create.call(this, gen: 'xy') naturePower = @battle.getMove('Nature Power') triAttack = @battle.getMove('Tri Attack') mock = @sandbox.mock(triAttack).expects('execute').once() .withArgs(@battle, @p1, [ @p2 ]) @battle.performMove(@p1, naturePower) mock.verify() describe "Venom Drench", -> it "lowers the target's attack, special attack, and speed by 1 stage if it is poisoned", -> shared.create.call(this, gen: 'xy') @p2.attach(Status.Poison) @battle.performMove(@p1, @battle.getMove('Venom Drench')) @p2.stages.should.containEql attack: -1, specialAttack: -1, speed: -1 it "fails if the target isn't poisoned", -> shared.create.call(this, gen: 'xy') venomDrench = @battle.getMove("Venom Drench") mock = @sandbox.mock(venomDrench).expects('fail').once() @battle.performMove(@p1, venomDrench) mock.verify() describe "Topsy-Turvy", -> it "reverses the target's boosts", -> shared.create.call(this, gen: 'xy') @p2.stages.attack = 2 @p2.stages.defense = -3 @p2.stages.speed = 0 @battle.performMove(@p1, @battle.getMove('Topsy-Turvy')) @p2.stages.should.containEql attack: -2 @p2.stages.should.containEql defense: 3 @p2.stages.should.containEql speed: 0 it "fails if the target has no boosts", -> shared.create.call(this, gen: 'xy') topsyTurvy = @battle.getMove('Topsy-Turvy') mock = @sandbox.mock(topsyTurvy).expects('fail').once() @battle.performMove(@p1, topsyTurvy) mock.verify() describe "Fell Stinger", -> it "raises the user's Attack 2 stages if the target faints", -> shared.create.call(this, gen: 'xy') @p2.currentHP = 1 @battle.performMove(@p1, @battle.getMove("Fell Stinger")) @p1.stages.should.containEql attack: 2 it "does not raise the user's Attack 2 stages otherwise", -> shared.create.call(this, gen: 'xy') @battle.performMove(@p1, @battle.getMove("Fell Stinger")) @p1.stages.should.containEql attack: 0 describe "Skill Swap", -> it "can swap the abilities if they are the same", -> shared.create.call this, gen: 'xy' team1: [Factory("Magikarp", ability: "Swift Swim")] team2: [Factory("Magikarp", ability: "Swift Swim")] skillSwap = @battle.getMove("Skill Swap") mock = @sandbox.mock(skillSwap).expects('fail').never() @battle.performMove(@p1, skillSwap) mock.verify() describe "Metronome", -> it "reselects if chosen an illegal move", -> shared.create.call(this, gen: 'xy') @p1.moves = [ metronome ] metronome = @battle.getMove("Metronome") belch = @battle.getMove("Belch") tackle = @battle.getMove("Tackle") index = @battle.MoveList.indexOf(belch) reselectIndex = @battle.MoveList.indexOf(tackle) shared.biasRNG.call(this, 'randInt', "metronome", index) shared.biasRNG.call(this, 'randInt', "metronome reselect", reselectIndex) mock = @sandbox.mock(tackle).expects('execute').once() @battle.performMove(@p1, metronome) mock.verify() testDelayedAttackMove = (moveName, type) -> describe moveName, -> it "does not hit substitutes if the user has Infiltrator and is active", -> shared.create.call this, gen: 'xy' team1: [Factory("Magikarp", ability: "Infiltrator")] move = @battle.getMove(moveName) @battle.performMove(@p1, move) @p2.attach(Attachment.Substitute, hp: 1) @battle.endTurn() @battle.endTurn() @p2.has(Attachment.Substitute).should.be.true @battle.endTurn() @p2.has(Attachment.Substitute).should.be.true it "always hits substitutes if the user is not on the field", -> shared.create.call this, gen: 'xy' team1: [Factory("Magikarp", ability: "Infiltrator"), Factory("Magikarp")] move = @battle.getMove(moveName) @battle.performMove(@p1, move) @p2.attach(Attachment.Substitute, hp: 1) @battle.endTurn() @battle.performSwitch(@p1, 1) @battle.endTurn() @p2.has(Attachment.Substitute).should.be.true @battle.endTurn() @p2.has(Attachment.Substitute).should.be.false testDelayedAttackMove("Future Sight") testDelayedAttackMove("Doom Desire")