Jump to content
Sign in to follow this  
silverlime

Error with Forewarn and AI (I think)

Recommended Posts

As I have implemented Reborn/Rejuvenation AI & Field Effects, I often find myself looking through the scripts of both games. One thing I noticed with Forewarn was that code was added which I think was meant to add the detected move to the AI move memory. However, there seem to be a few problems that I've found (Sorry this is kind of long. I've been working through it to fix it for my game as well):

 

The code for forewarn starts with this line:

if self.hasWorkingAbility(:FOREWARN) && @battle.pbOwnedByPlayer?(@index) && onactive

but this means that if an opponent's Pokemon is the one with Forewarn, it will just skip over activating, meaning that the AI will not detect an opposing Pokemon's moves if it is the one sending out a Pokemon with Forewarn.

 

 

Then here's the bigger problem:

   if moves.length>0
        move=moves[@battle.pbRandom(moves.length)]
        movename=PBMoves.getName(move)
        @battle.pbDisplay(_INTL("{1}'s Forewarn alerted it to {2}!",pbThis,movename))        
        if (self.index==0 || self.index==2) && !@battle.isOnline? # Move memory system for AI
          warnedMove = PokeBattle_Move.pbFromPBMove(@battle,PBMove.new(move),self)
          if @battle.aiMoveMemory[0].length==0 && warnedMove.basedamage!=0
            @battle.aiMoveMemory[0].push(warnedMove)
          elsif @battle.aiMoveMemory[0].length!=0 && warnedMove.basedamage!=0          
            dam1=@battle.pbRoughDamage(warnedMove,self,@battle.battlers[1],255,warnedMove.basedamage)
            dam2=@battle.pbRoughDamage(@battle.aiMoveMemory[0][0],self,@battle.battlers[1],255,@battle.aiMoveMemory[0][0].basedamage)
            if dam1>dam2
              @battle.aiMoveMemory[0].clear
              @battle.aiMoveMemory[0].push(warnedMove)
            end          
          end                    
          if @battle.aiMoveMemory[1].length==0 
            @battle.aiMoveMemory[1].push(warnedMove)        
          else
            dupecheck=0
            for i in @battle.aiMoveMemory[1]
              dupecheck+=1 if i.id == warnedMove.id
            end
            @battle.aiMoveMemory[1].push(warnedMove) if dupecheck==0
          end 
          if @battle.aiMoveMemory[2][self.pokemonIndex].length==0 
            @battle.aiMoveMemory[2][self.pokemonIndex].push(warnedMove)        
          else
            dupecheck=0
            for i in @battle.aiMoveMemory[2][self.pokemonIndex]
              dupecheck+=1 if i.id == warnedMove.id
            end
            @battle.aiMoveMemory[2][self.pokemonIndex].push(warnedMove) if dupecheck==0
          end         
        end        
      end

This code (starting with the line with the comment '# Move memory system for AI') seems to have been copied from the other area in Pokebattle_Battler where the AI remembers which move one of the player's Pokemon uses except that it was changed to use warnedMove instead of choice[2]. Since this was the only change made, each time it refers to self it is referring to the Pokemon with Forewarn, not the actual Pokemon with the move. However, this introduces yet another problem because Forewarn doesn't reveal which opponent has the move in double battles.

 

Based on how the code is currently, I think it would work like the following (though there's not an easy way to actually see how it would work so I'm just going off logic):

If the Pokemon with Forewarn is owned by the player, the message will be played correctly, stating the move that was detected on the opponent's Pokemon. Then, the AI registers the the move detected on its own Pokemon as a move of the player's Pokemon.

It should work so that if the player's Pokemon has Forewarn, the AI doesn't remember the move, and only a message should be played. If the AI sends out the Pokemon with Forewarn, it should register the move detected on the player's Pokemon as a move of that Pokemon.

 

I've tried to fix the code for my own game and I'll post it here in case it's correct or helpful (I made it so the player and opponent are both alerted which Pokemon carries the move, but I'm still not really sure how the aiMoveMemory array works so there might be a problem with that):

    # Forewarn
    if self.hasWorkingAbility(:FOREWARN) && onactive
      PBDebug.log("[Ability triggered] #{pbThis} has Forewarn")
      highpower=0
      fwmoves=[]
      moveusers=[]
      for foe in [pbOpposing1,pbOpposing2]
        next if foe.fainted?
        for j in foe.moves
          movedata=PBMoveData.new(j.id)
          power=movedata.basedamage
          power=160 if movedata.function==0x70    # OHKO
          power=150 if movedata.function==0x8B    # Eruption
          power=120 if movedata.function==0x71 || # Counter
                       movedata.function==0x72 || # Mirror Coat
                       movedata.function==0x73 || # Metal Burst
          power=80 if movedata.function==0x6A ||  # SonicBoom
                      movedata.function==0x6B ||  # Dragon Rage
                      movedata.function==0x6D ||  # Night Shade
                      movedata.function==0x6E ||  # Endeavor
                      movedata.function==0x6F ||  # Psywave
                      movedata.function==0x89 ||  # Return
                      movedata.function==0x8A ||  # Frustration
                      movedata.function==0x8C ||  # Crush Grip
                      movedata.function==0x8D ||  # Gyro Ball
                      movedata.function==0x90 ||  # Hidden Power
                      movedata.function==0x96 ||  # Natural Gift
                      movedata.function==0x97 ||  # Trump Card
                      movedata.function==0x98 ||  # Flail
                      movedata.function==0x9A     # Grass Knot
          if power>highpower
            fwmoves=[j.id]
            highpower=power
            moveusers=[foe]
          elsif power==highpower
            fwmoves.push(j.id)
            moveusers.push(foe)
          end
        end
      end
      r=@battle.pbRandom(fwmoves.length)
      fwmove=fwmoves[r]
      fwuser=moveusers[r]
      if @battle.pbOwnedByPlayer?(@index)
        if fwmoves.length>0
          movename=PBMoves.getName(fwmove)
          @battle.pbDisplay(_INTL("{1}'s Forewarn alerted it to {2}'s {3}!",pbThis,fwuser.pbThis,movename))
        end
      elsif @battle.pbIsOpposing?(@index)
        if fwmoves.length>0
          warnedMove = PokeBattle_Move.pbFromPBMove(@battle,PBMove.new(fwmove))
          if @battle.aiMoveMemory[0].length==0 && warnedMove.basedamage!=0
            @battle.aiMoveMemory[0].push(warnedMove)
          elsif @battle.aiMoveMemory[0].length!=0 && warnedMove.basedamage!=0          
            dam1=@battle.pbRoughDamage(warnedMove,fwuser,self,255,warnedMove.basedamage)
            dam2=@battle.pbRoughDamage(@battle.aiMoveMemory[0][0],fwuser,self,255,@battle.aiMoveMemory[0][0].basedamage)
            if dam1>dam2
              @battle.aiMoveMemory[0].clear
              @battle.aiMoveMemory[0].push(warnedMove)
            end          
          end                    
          if @battle.aiMoveMemory[1].length==0 
            @battle.aiMoveMemory[1].push(warnedMove)        
          else
            dupecheck=0
            for i in @battle.aiMoveMemory[1]
              dupecheck+=1 if i.id == warnedMove.id
            end
            @battle.aiMoveMemory[1].push(warnedMove) if dupecheck==0
          end 
          if @battle.aiMoveMemory[2][fwuser.pokemonIndex].length==0 
            @battle.aiMoveMemory[2][fwuser.pokemonIndex].push(warnedMove)        
          else
            dupecheck=0
            for i in @battle.aiMoveMemory[2][fwuser.pokemonIndex]
              dupecheck+=1 if i.id == warnedMove.id
            end
            @battle.aiMoveMemory[2][fwuser.pokemonIndex].push(warnedMove) if dupecheck==0
          end         
        end   
      end
    end

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...