<?

// --------------------------------------------------------------------------------
// bpkm handler class - the Pok├ęcheck VS. Player - https://www.pokecheck.org
// Damage calculation http://www.smogon.com/bw/articles/bw_complete_damage_formula
// Researched by Xfr, Bond697 & Kaphotics
// License: PUBLIC DOMAIN except for all copyrighted names and trademarks
// --------------------------------------------------------------------------------

class BPkm
{
 public 
$hex "";
 public 
$pid;
 public 
$exp;
 public 
$dex;
 public 
$tid;
 public 
$sid;
 public 
$item;
 public 
$happiness;
 public 
$ability;
 public 
$oability;
 public 
$nature;
 public 
$evs;
 public 
$ivs;
 public 
$riv;
 public 
$rev;
 public 
$moves;
 public 
$pp;
 public 
$gender;
 public 
$form;
 public 
$oform;
 public 
$rnick;
 public 
$nick;
 public 
$rot;
 public 
$ot;
 public 
$ball;
 public 
$lang;
 public 
$lvl;
 public 
$bstats;
 public 
$obstats;
 public 
$base;
 public 
$fateful;
 public 
$shiny;
 public 
$dexinfo;
 public 
$hpt;
 public 
$hpp;

 public 
$player;
 public 
$slot;
 public 
$id;
 public 
$U;

 public 
$hp;
 public 
$planned;
 public 
$params;
 public 
$type1$type2;

 public 
$statups = array(0,0,0,0,0,0,0);
 public 
$stockpile 0;
 public 
$critlevel 0;
 public 
$lastitem 0;
 public 
$status 0;
 public 
$volatile 0;
 public 
$volatile2 0;
 public 
$toxiccount 0;
 public 
$perishcount 0;
 public 
$sleepcount 0;
 public 
$sleepturns 0;
 public 
$confturns 0;
 public 
$trapturns 0;
 public 
$encoreturns 0;
 public 
$disableturns 0;
 public 
$hbturns 0;
 public 
$mturns 0;
 public 
$disabled 0;
 public 
$trapper null;
 public 
$tauntturns 0;
 public 
$grounded 0;
 public 
$subhp 0;
 public 
$hadsub 0;
 public 
$turncount 0;
 public 
$protectcount 0;
 public 
$quickclaw 2;
 public 
$unaware 0;
 public 
$unburden 0;
 public 
$mindread 0;
 public 
$hurtby = array();
 public 
$hasmoved 0;
 public 
$mcharge 0;
 public 
$mimic 0;
 public 
$onfield 0;
 public 
$switching 0;
 public 
$history = array();
 public 
$hhistory = array();
 public 
$shistory = array();
 public 
$leecher$lover;

 const 
F_NONE 0;
 const 
F_CONFUSED 1;
 const 
F_INFATUATED 2;
 const 
F_TRAPPED 4;
 const 
F_NIGHTMARE 8;
 const 
F_TAUNTED 16;
 const 
F_CHARGE 32;
 const 
F_TORMENT 64;
 const 
F_DISABLE 128;
 const 
F_YAWN 256;
 const 
F_HEALBLOCK 512;
 const 
F_FLASHFIRE 1024;
 const 
F_NOIMMUNITY 2048;
 const 
F_LEECHED 4096;
 const 
F_EMBARGO 8192;
 const 
F_PERISH 16384;
 const 
F_INGRAIN 32768;
 const 
F_IMPRISON 65536;
 const 
F_MAGNETRISE 131072;
 const 
F_POWERTRICK 262144;
 const 
F_ENCORE 524288;
 const 
F_CURSE 1048576;
 const 
F_YAWN2 2097152;
 const 
F_AQUARING 4194304;
 const 
F_DESTINYBOND 8388608;

 public static 
$vlabel = array
 (
  
self::F_CONFUSED=>"confused",
  
self::F_INFATUATED => "infatuated",
  
self::F_TRAPPED=>"trapped",
  
self::F_NIGHTMARE=>"having a nightmare",
  
self::F_TAUNTED => "taunted",
  
self::F_CHARGE => "charging",
  
self::F_TORMENT=>"tormented",
  
self::F_DISABLE=>"unable to use its last move again",
  
self::F_YAWN => "feeling drowsy",
  
self::F_EMBARGO => "prevented from using its item",
  
self::F_HEALBLOCK=>"unable to heal",
  
self::F_LEECHED=>"infected",
  
self::F_PERISH=>"under the effect of perish song",
  
self::F_INGRAIN=>"rooted",
  
self::F_IMPRISON=>"preventing foes from using its moves",
  
self::F_MAGNETRISE=>"levitating",
  
self::F_POWERTRICK=>"switching its attack and defense",
  
self::F_ENCORE=>"forced to use the same move"
 
);

 public static 
$slabel = array
 (
  
self::S_NONE=>"cured of status problems",
  
self::S_PARALYZED=>"paralyzed",
  
self::S_POISON=>"poisoned",
  
self::S_TOXIC=>"badly poisoned",
  
self::S_BURNED=>"burned",
  
self::S_ASLEEP=>"asleep",
  
self::S_FREEZE=>"frozen",
  
self::S_FAINTED=>"fainted"
 
);

 public static 
$stag = array
 (
  
self::S_NONE=>"",
  
self::S_PARALYZED=>"par",
  
self::S_POISON=>"psn",
  
self::S_TOXIC=>"tox",
  
self::S_BURNED=>"brn",
  
self::S_ASLEEP=>"slp",
  
self::S_FREEZE=>"frz",
  
self::S_FAINTED=>"fnt"
 
);

 const 
F2_NONE 0;
 const 
F2_FLINCHED 1;
 const 
F2_PROTECT 2;
 const 
F2_WIDEGUARD 4;
 const 
F2_HELPINGHAND 8;
 const 
F2_MEFIRST 16;
 const 
F2_GROUNDED 32;
 const 
F2_MAGICCOAT 64;
 const 
F2_RAGEPOWDER 128;

 const 
F2_QUICKGUARD 512;
 const 
F2_ENDURE 1024;
 const 
F2_YAWN1 2048;
 const 
F2_YAWN2 4096;
 const 
F2_NOTORMENT 8192;

 const 
S_NONE 0;
 const 
S_PARALYZED 1;
 const 
S_ASLEEP 2;
 const 
S_FREEZE 3;
 const 
S_BURNED 4;
 const 
S_POISON 5;
 const 
S_TOXIC 6;
 const 
S_FAINTED 7;

 const 
E_SENDOUT 0;
 const 
E_TURNSTART 1;
 const 
E_PREATTACK 2;
 const 
E_AFFECTED 3;
 const 
E_ATTACK 4;
 const 
E_EFFECTS 5;
 const 
E_FINALEFFECTS 6;
 const 
E_POSTATTACK 7;
 const 
E_FAINTED 8;
 const 
E_TURNEND 9;
 const 
E_WEATHER 10;
 const 
E_SWITCHOUT 11;
 const 
E_FAIL 12;
 const 
E_ITEMUPK 13;
 const 
E_LEECHUPK 14;
 const 
E_STATUSUPK 15;
 const 
E_FINALUPK 16;
 const 
E_PREATTACK2 17;

 
// Unified function for output
 // Supports alternative codec (JS-style replay)
 
function O($txt$js$raw=false)
 {
  global 
$JSOUT$JS;

  if(
$raw && $raw>0){ echo $txt?($JSOUT?'':$txt):($JSOUT?$js:''); return; }
  
$u = isset($this->params['user'])?$this->params['user']:$this;
  
$t $this;

  
// Text log output callback
  
$cb = function($m) use(&$t,&$u)
  {
   global 
$players$partys$log$BV$MOVES$ABILITIES$ITEMS$JSOUT;
   if(isset(
$m[2])) $p explode(",",substr($m[2],1,-1));
   else 
$p = array();

   switch(
$m[1])
   {
    case 
"ab":
     if(
$JSOUT) return $ABILITIES[count($p)?$p[0]:$t->ability];
     return 
"<span class=\"ability\">".$ABILITIES[count($p)?$p[0]:$t->ability]."</span>";
    case 
"n":
     if(
$JSOUT) return $t->rnick;
     return 
"<span class=\"pokemon\">{$t->nick}</span>";
    case 
"lvl": return $t->lvl;
    case 
"species":
     if(
$JSOUT) return $t->dexinfo['name'].($t->oform?"-".$GLOBALS['forms'][$t->dex][$t->oform]:'');
     return 
"<span class=\"pokemon\">{$t->dexinfo['name']}</span>";
    case 
"fspecies":
     return 
$t->dexinfo['name'].((count($p)?$t->dexinfo['form']:$t->oform)?"-".$GLOBALS['forms'][$t->dex][$t->oform]:'')
            .
", L{$t->lvl}".($t->gender==1?", F":(!$t->gender?", M":"")).($t->shiny?", shiny":"");
    case 
"un":
     if(
$JSOUT) return $u->rnick;
     return 
"<span class=\"pokemon\">{$u->nick}</span>";
    case 
"opp":
     if(
$JSOUT) return "p".(2-($t->player%2)).": ".($players[1-($t->player%2)]->uname);
     return 
"<span class=\"player".(1-($t->player%2))."\">".($players[1-($t->player%2)]->name)."</span>";
    case 
"p":
     if(
$JSOUT) return "p".(1+($t->player%2)).": ".$players[$t->player]->uname;
     return 
"<span class=\"player{$t->player}\">{$players[$t->player]->name}</span>";
    case 
"rp":
     return 
$players[$t->player]->uname;
    case 
"fslot"$full true; goto _slot;
    case 
"slot"$full false_slot:
     
$tmp = array("a","b","c","d","e","f");
     
$pk count($p) ? $players[$p[0]]->party[$p[1]] : $t;

     
$slot array_search($pk->id$partys[$pk->player]);
     if(
$pk->player 1$slot++;

     return 
"p".(1+($pk->player%2)).($BV->type?$tmp[$slot]:'')
            .(
$full ": {$pk->rnick}""");
    case 
"hpc":
     return 
ceil($t->getstat(0,1))."/100".($t->status?" ".BPkm::$stag[$t->status]:"");
    case 
"up":
     if(
$JSOUT) return "p".(1+($u->player%2)).": ".$players[$u->player]->uname;
     return 
"<span class=\"player{$u->player}\">{$players[$u->player]->name}</span>";
    case 
"m":
     
$mid count($p) ? $p[0] : $t->params['move'];
     if(
$JSOUT) return $MOVES[$mid]["name"];
     return 
"<span class=\"move\">".$MOVES[$mid]["name"]."</span>";
    case 
"status":
     if(
$JSOUT) return BPkm::$stag[count($p)?$p[0]:$t->status];
     return 
BPkm::$slabel[count($p)?$p[0]:$t->status];
    case 
"volatile":
     return 
BPkm::$vlabel[$p[0]];
    case 
"st":
     
$tmp = array("atk","def","spa","spd","spe","accuracy","evasion");
     if(
$JSOUT) return $tmp[$p[0]-2];
     return 
$GLOBALS['statnames'][$p[0]-1];
    case 
"item":
     
$p[] = $t->item;
     if(isset(
$ITEMS[$p[0]])) $n $ITEMS[$p[0]];
     else
     {
      
$q mysql_query("SELECT * FROM items WHERE id='{$p[0]}' AND lang='2'");
      if(
$r mysql_fetch_assoc($q)) $n $ITEMS[$p[0]] = $r;
      else 
$n = array("name"=>"Unknown({$p[0]})");
     }
     
$n $n['name'];
     if(
$JSOUT) return $n;
     return 
"<span class=\"item\">$n</span>";
    case 
"pkn":
     
$pk $players[$p[0]]->party[$p[1]];
     if(
$JSOUT) return $pk->rnick;
     return 
"<span class=\"pokemon\">{$pk->nick}</span>";
    default: return 
'';
   }
  };

  if(
$JSOUT)
  {
   if(
$js==="") return;
   
$tmp preg_replace_callback("/%([a-z]+)(\([^)]+\))?%?/"$cb$js);
   if(
$raw) return $tmp;
   
$JS[] = $tmp;
  }
  else
  {
   if(
$txt==="") return;
   
$tmp preg_replace_callback("/%([a-z]+)(\([^)]+\))?%?/"$cb$txt)."<br />";
   if(
$raw) return $tmp;
   echo 
$tmp;
  }
 }

 
// There are many problems with this function (written before research was completed)
 // The accuracy system is ironically not accurate. This deserves an addentum to the damage calc article
 // Accuracy works like the damage formula, using separate triggers for base value, accuracy and evasion
 // Applying some modifiers to the stats rather than base value (e.g. BrightPowder) will ruin the rounding
 // when chaining them (typical example: Sand Veil+BrightPowder Garchomp). Left as TODO for now
 // (current simulators also implement accuracy mostly wrong, a ref would definitely help)
 // The same problem also exists for speed - TODO document 21BC968 and the 0x13 trigger set
 // It's interesting to note that global triggers (typically affecting the whole field and located in VRAM)
 // such as Tailwind still apply when fainted. They should be implemented separately. TODO
 
function getstat($stat$crit=0$mod=0x1000$notriggers=false)
 {
  global 
$BV;

  if(
$stat == 0) return $crit ? ($this->hp*100/$this->bstats[1]) : $this->hp;

  
$mul $this->statups[$stat-1];
  
$user = isset($this->params['user'])?$this->params['user']:false;
  
$target = isset($this->params['target'])?$this->params['target']:false;
  
$mid = isset($this->params['move'])?$this->params['move']:0;
  
$eid $mid?getmeta($mid):0; if($eid$eid=$eid['effect'];

  if(
$user && $target // Unaware, stat boost ignore moves (Sacred Sword)
    
&& (($user != $this && ($user->ability == 109 || $eid == 304)) // Defense boosts
    
|| ($user == $this && $target->mbability($this) == 109))) $mul=0// Attack boosts

  
if($stat==|| $stat==7$base 100;
  else
  {
   
$s $stat;
   if(
$this->volatile self::F_POWERTRICK)
   {
    if(
$s == 1$s 2;
    else if(
$s == 2$s 1;
   }
   
$base $this->bstats[$s+1];
  }

  if((!
$this->hp && $eid!=8) || $crit 0)
  {
   
// Global triggers still apply when fainted, e.g. tailwind for replacement speed ties (495431100665@5)
   // Generally global triggers apply last, which means a refactor is required... TODO TODO TODO
   
if($stat==&& $BV->sidee[$this->player%2] & BVideo::S_TAILWIND$base <<= 1;
   return 
$base;
  }

  if(
$stat==|| $stat==7)
  {
   if(
$stat==&& $BV->gravityt$mul min(6$mul+2);
   if(
$mul >= 0$res = (int)($base * (6+2*$mul)/6);
   else 
$res = (int)($base*6/(2*$mul));
  }
  else if(!(
$crit && (($mul>&& in_array($stat, array(2,4)))||($mul<&& in_array($stat,array(1,3))))))
  {
   if(
$mul >= 0$res = (int)($base*(2+$mul)/2);
   else 
$res = (int)(($base*2)/(2-$mul));
  }
  else 
$res $base;

  
// GetBPkmStat()
  
if($notriggers) return $res;

  switch(
$stat)
  {
   case 
1// Attack
    
if($BV->fgift[$this->player%2] && $this->mbability()) // Flower Gift
     
chainmod($mod0x1800);

    switch(
$this->ability)
    {
     case 
62// Guts
      
if($this->statuschainmod($mod0x1800);
     break;
     case 
37: case 74// Pure/Huge power
      
chainmod($mod0x2000);
     break;
     case 
55// Hustle
      
$res applymod($res0x1800);
     break;
     case 
112// Slow Start
      
if($this->turncount 5chainmod($mod0x800);
     break;
    }
    switch(
$this->getitem())
    {
     case 
220// Choice band
      
chainmod($mod0x1800);
     break;
     case 
236// Light Ball
      
if($this->dex == 25chainmod($mod0x2000);
     break;
     case 
258// Thick Club
      
if($this->dex == 104 || $this->dex == 105chainmod($mod0x2000);
     break;
    }
   break;

   case 
2// Defense
    
switch($this->mbability())
    {
     case 
63// Marvel Scale
      
if($this->statuschainmod($mod0x1800);
     break;
    }
    switch(
$this->getitem())
    {
     case 
257// Metal Powder
      
if($this->dex == 132chainmod($mod0x2000);
     break;
     case 
538// Evolite
      
if(mysql_result(mysql_query("SELECT COUNT(*) FROM dex WHERE evo='{$this->dex}'"),0)) chainmod($mod0x1800);
     break;
    }
   break;

   case 
3// Special Attack
    
switch($this->ability)
    {
     case 
94// Solar Power
      
if($BV->getweather() == BVideo::W_SUNchainmod($mod0x1800);
     break;
     case 
57: case 58// Plus, Minus
      
$a $this->ability==57?58:57;
      if(isset(
$this->params['allies']))
      foreach(
$this->params['allies'] as $p)
       if(
$p->hp && $p->ability == $a)
       {
        
chainmod($mod0x1800);
        break;
       }
     break;
    }
    switch(
$this->getitem())
    {
     case 
297// Choice specs
      
chainmod($mod0x1800);
     break;
     case 
236// Light Ball
      
if($this->dex == 25chainmod($mod0x2000);
     break;
     case 
225// Soul Dew
      
if(in_array($this->dex, array(380381))) chainmod($mod0x1800);
     break;
     case 
226// DeepSeaTooth
      
if($this->dex == 366chainmod($mod0x2000);
     break;
    }
   break;

   case 
4// Special Defense
    // SD boost in Sandstorm
    
if($BV->getweather() == BVideo::W_SAND && ($this->type1==6||$this->type2==6)) $res applymod($res0x1800);
    
// Flower Gift
    
if($BV->fgift[$this->player%2] && $this->mbability()) chainmod($mod0x1800);

    switch(
$this->getitem())
    {
     case 
225// Soul Dew
      
if(in_array($this->dex, array(380381))) chainmod($mod0x1800);
     break;
     case 
227// DeepSeaScale
      
if($this->dex == 366chainmod($mod0x2000);
     break;
     case 
538// Evolite
      
if(mysql_result(mysql_query("SELECT COUNT(*) FROM dex WHERE evo='{$this->dex}'"),0)) chainmod($mod0x1800);
     break;
    }
   break;

   case 
5//Speed
    
switch($this->ability)
    {
     case 
146// Sand Rush
      
if($BV->getweather() == BVideo::W_SAND$res *= 2;
     break;
     case 
95// Quick Feet
      
if($this->status$res = (int)($res*1.5);
     break;
     case 
33// Swift Swim
      
if($BV->getweather() == BVideo::W_RAIN$res <<=1;
     break;
     case 
34// Chlorophyll
      
if($BV->getweather() == BVideo::W_SUN$res <<=1;
     break;
     case 
112// Slow Start
      
if($this->turncount 5$res >>= 1;
     break;
    }

    switch(
$this->getitem())
    {
     case 
287// Choice Scarf
      
$res = (int)($res*1.5);
     break;
    }

    switch(
$this->item// Not affected by Klutz
    
{
     case 
278: case 293: case 292: case 290: case 291: case 294: case 289: case 215// Power items, Iron Ball
      
$res >>= 1;
     break;
    }

    
// Tailwind
    
if($BV->sidee[$this->player%2] & BVideo::S_TAILWIND$res <<= 1;

    
// Unburden
    
if($this->unburden$res <<= 1;

    
// Paralysis
    
if($this->status == self::S_PARALYZED && $this->ability != 95$res>>=2;
   break;

   case 
6// Accuracy
    // Victory Star
    
if(isset($this->params['allies']))
    foreach(
$this->params['allies'] as $pk)
     if(
$pk->ability == 162$res = (int)($res*1.1);

    switch(
$this->ability)
    {
     case 
55// Hustle
      
if($mid && $GLOBALS['MOVES'][$mid]['cat']==2)
       
$res = (int)($res*0.8);
     break;
     case 
14// Compoundeyes
      
$res = (int)($res*1.3);
     break;
    }
    switch(
$this->getitem())
    {
     case 
265// Wide Lens
      
$res = (int)($res*1.1);
     break;
    }
    if(
$target// 131966391454 BrightPower lowers accuracy
    
switch($target->getitem())
    {
     case 
255// Lax Incense
     
case 213// BrightPowder
      
$res = (int)($res*0.9);
     break;
    }
   break;

   case 
7// Evasion
    
switch($this->mbability())
    {
     case 
81// Snow Cloak
      
if($BV->getweather() == BVideo::W_HAIL$res = (int)($res*1.25);
     break;
     case 
8// Sand Veil
      
if($BV->getweather() == BVideo::W_SAND$res = (int)($res*1.25);
     break;
     case 
77// Tangled Feet
      
if($this->volatile self::F_CONFUSED$res <<= 1;
     break;
     case 
147// Wonder Skin
      
if(isset($this->params['move']) && ($mid=$this->params['move']))
      switch(
$eid $GLOBALS['META'][$mid]['class'])
      {
       
// Status move, stat moves
       
case 1: case 2$res <<= 1;
      }
     break;
    }
   break;
  }

  
BVideo::debug("Get stat($stat) on {$this->nick} = $res [$mod]");
  return 
applymod($res$mod);
 }

 function 
statchange($s$v$foe=false$from "")
 {
  global 
$BV;
  if(
$foe && $BV->sidee[$this->player%2] & BVideo::S_MIST)
  {
   
$this->O("%n is protected by the mist!","|-activate|%fslot|mist");
   return 
false;
  }

  switch(
$this->mbability())
  {
   case 
51// Keen Eye
    
if($s==7) return false;
   break;
   case 
29// Clear Body
    
if($v && $foe) return false;
   break;
   case 
52// Hyper Cutter
    
if($s==&& $v<0) return false;
   break;
   case 
73// White Smoke
    
if($foe && $v<0) return false;
   break;
   case 
86// Simple
    
$v *= 2;
   break;
   case 
126// Contrary
    
$v *= -1;
   break;
   case 
128// Defiant
    
if($v && $foe)
    {
     
$this->statchange(22);
    }    
   break;
   case 
145// Big Pecks
    
if($s==&& $v<0) return false;
   break;
  }

  if(
abs($this->statups[$s-2]) == 6) return false;

  
$this->statups[$s-2] = min(6$this->statups[$s-2]+$v);
  
$this->O("%n's %st($s) ".(abs($v)>2?'drastically':(abs($v)>1?'sharply':''))." ".($v>0?'increased':'fell')."!",
   
"|-".($v>0?"":"un")."boost|%fslot|%st($s)|".abs($v).($from?"|$from":''));
  return 
true;
 }

 function 
setstatus($s$perm$from="")
 {
  global 
$ITEMS$BV;

  
$o_s $s;
  if(!
$this->hp && $s) return false;

  
// Leaf Guard
  
if($this->mbability() == 102 && $BV->getweather() == BVideo::W_SUN) return false;

  
// Type and ability canceling status
  
if($perm || (!$perm && $s==self::F_CONFUSED))
  {
   
// Safegaurd
   
if($s && $BV->sidee[$this->player%2] & BVideo::S_SAFEGUARD && 
    !(isset(
$this->params['user']) && $this->params['user']->ability==151)) return false;

   if(
$perm)
   switch(
$s)
   {
    case 
self::S_TOXIC:  // Steel / Poison type
    
case self::S_POISON// Immunity
     
if(count(array_intersect(array($this->type1,$this->type2),array(9,4)))
      || 
$this->mbability() == 17) return false;
    break;
    case 
self::S_BURNED// Water Veil
     
if($this->type1 == 10 || $this->type2 == 10 || $this->mbability() == 41) return false;
    break;
    case 
self::S_PARALYZED// Limber
     
if($this->mbability() == 7) return false;
    break;
    case 
self::S_FREEZE// Magma Armor
     
if($this->type1 == 15 || $this->type2 == 15 || $this->mbability() == 40 || $BV->getweather() == BVideo::W_SUN)
      return 
false;
    break;
    case 
self::S_ASLEEP// Insomnia
     
if($this->mbability() == 15 || $this->mbability() == 72) return false;
    break;
   }
   else if(
$s==self::F_CONFUSED// Own Tempo
    
if($this->mbability() == 20) return false;
   else if(
$s==self::F_INFATUATED// Oblivious
    
if($this->mbability() == 12) return false;
  }

  if(
$perm)
  {
   if(!
$s && $this->status != self::S_FAINTED)
   {
    
$this->toxiccount 0;

    if(
$this->status)
     
$this->O("%n is no longer %status!","|-curestatus|%fslot".($from?"|$from":''));

    
$this->status $s;
    return 
true;
   }
   else if(
$this->status != self::S_NONE && $this->status != self::S_FAINTED && // Can't override status
    
!(isset($this->params['move']) && $this->params['move'] == 156 && $this->status != self::S_ASLEEP)) // except Rest
   
{
    
$this->O("%n is already %status!","|-fail|%fslot|%status");
    return 
false;
   }
   else
   {
    if(
$s == self::S_ASLEEP)
    {
     
$this->sleepturns = isset($this->params['randduration']) ? $this->params['randduration'] : $BV->rand(3)+2;;
     
$this->sleepcount $this->sleepturns;
    }

    
$this->O("%n is %status($s)!","|-status|%fslot|%status($s)".($from?"|$from":""));

    if(
$s == self::S_TOXIC)
    {
     
$this->toxiccount 1;
     
$s self::S_POISON;
    }
    
$this->status $s;
   }

   
// Synchronize
   
if(isset($this->params['user']) && $this->ability == 28 && !in_array($o_s, array(self::S_ASLEEPself::S_FREEZE)))
   {
    
$this->O("%n synchronized its status with %un!","");
    
$this->params['user']->setstatus($o_strue);
   }

   
$this->checkitem();
   return 
true;
  }

  if(
$this->volatile $s)
  {
   
$this->O("%n is already %volatile($s)!","");
   return 
false;
  }

  
$etag "";
  switch(
$s)
  {
   case 
self::F_LEECHED:
    if(
$this->type1 == 12 || $this->type2 == 12)
    {
     
$this->O("%n is not affected","");
     return;
    }
    global 
$partys;
    
$this->leecher = array($p=$this->params['player'], array_search($this->params['pkid'],$partys[$p]));
    
$etag "leechseed";
   break;
   case 
self::F_INFATUATED:
    if(isset(
$this->params['user']) && (1-$this->gender) != $this->params['user']->gender)
    {
     
$this->O("%n isn't affected.","");
     return;
    }
    
$this->lover = array($this->params['player'], $this->params['pkid']);
    
$etag "attract";
   break;
   case 
self::F_CONFUSED:
    
$this->confturns = isset($this->params['confturns'])?$this->params['confturns']:$BV->rand(4)+2;
    
$etag "confusion";
   break;
   case 
self::F_TRAPPED:
    
$user $this->params['user'];
    if(!
$this->params['minduration']) $this->trapturns = -1;
    else if(
$user->getitem() == 286$this->trapturns 5;
    else 
$this->trapturns $this->params['randduration'];
    
//$this->params['minduration']+$BV->rand($this->params['randduration']);
    
$this->trapper $user;
   break;
   case 
self::F_HEALBLOCK:
    
$this->hbturns = isset($this->params['minduration']) ? $this->params['minduration'] : 5;
    
$etag "healblock";
   break;
   case 
self::F_CHARGE:
    
$this->O("","|-activate|%fslot|charge");
   break;
   case 
self::F_PERISH:
    if(
$this->ability == 43) return false;
    
$this->perishturns 4;
   break;
   case 
self::F_TAUNTED:
    
$this->tauntturns 3;
    
$etag "taunt";
   break;
   case 
self::F_ENCORE:
    if(!(
$lm=end($this->history)) || in_array($lm, array(227,102,119,166,165,144))
       || !
in_array($lm$this->moves)) return false;
    
$this->encoreturns 3;
    
$etag "encore";
   break;
   case 
self::F_DISABLE:
    if(!(
$lm=end($this->history))) return false;
    
$this->disabled $lm;
    
$this->disableturns 4;
    
$etag "disable";
   break;
   case 
self::F_YAWN:
    if(
$this->status) return $this->fail();
    
$this->volatile2 |= self::F2_YAWN1;
    
$etag "yawn";
   break;
   case 
self::F_TORMENT:
    
// 320280985649 Torment only starts after the first used move
    
$this->volatile2 |= self::F2_NOTORMENT;
   break;
  }

  
$this->O("%n is %volatile($s)!",$etag?"|-start|%fslot|$etag":"");
  
$this->volatile |= $s;
  
$this->checkitem();
  return 
true;
 }

 
// Mold Breaker helper for abilities affected by it
 
function mbability($user false)
 {
  if(!
$user && isset($this->params['user'])) $user $this->params['user'];
  if(
$user && $user != $this && in_array($user->ability, array(104163164))) return 0;
  return 
$this->ability;
 }

 function 
formchange($form)
 {
  global 
$DEX$forms;
  if(
$form == $this->form) return;

  
$DEX mysql_fetch_assoc(mysql_query("SELECT * FROM dex WHERE dex='{$this->dex}' AND form='$form'"));
  
$this->type1 $DEX['type1']; $this->type2 $DEX['type2'];
  for(
$i=2$i<7$i++)
  {
   
$this->bstats[$i] = statval($i$this->ivs[$i-1], $this->evs[$i-1], $this->lvl$this->nature);
  }

  
$this->form $form;
  
$fn $forms[$this->dex][$form];
  
$this->O("%n transformed into the $fn form!","|-formechange|%fslot|{$DEX['name']}-$fn");
 }

 function 
transform($pk)
 {
  if(
$pk->subhp) return false;
  
$this->bstats $pk->bstats;
  
$this->bstats[0] = $this->hp;
  
$this->bstats[1] = $this->obstats[1];
  
$this->statups $pk->statups;
  
$this->type1 $pk->type1;
  
$this->type2 $pk->type2;
  
$this->ability $pk->ability;
  
$this->O("%n copied %pkn({$pk->U})'s stats.","|-transform|%fslot|%fslot({$pk->U})");
 }

 
// Those trigger at switch in or when ability changes
 
function triggerability()
 {
  global 
$BV$ABILITIES$ITEMS$log$players$partys;

  if(
$this->ability == 150// Imposter
  
{
   if(
$pk $this->facingop())
   {
    
$this->transform($pk);
   }
  }

  switch(
$this->ability)
  {
   case 
36// Trace
    
if(($pk=$this->randop()) && !in_array($pk->ability, array(36121149)))
    {
     
$this->O("%n traced %pkn({$pk->U})'s %ab({$pk->ability})!","");
     
$this->setability($pk->ability,"|[from] trace|[of] %fslot({$pk->U})");
    }
   break;

   case 
88// Download
    
if(isset($this->params['opponents']))
    {
     
$def 0$sd 0;
     foreach(
$this->params['opponents'] as $o)
     {
      
$def += $o->getstat(2);
      
$sd += $o->getstat(4);
     }
     
$this->O("%n downloaded a".($def>=$sd?' Special':'n')." Attack boost.","");
     
$this->statchange($def >= $sd 210"[from] download|[of] %fslot({$this->U})");
    }
   break;

   case 
22// Intimidate
    
$this->O("%n is intimidating its opponents!","");
    foreach(
$this->params['opponents'] as $tmp)
     if(
$tmp->hp && !$tmp->subhp)
     {
      
$this->O("","|-ability|%fslot|%ab|[of] %fslot({$tmp->U})");
      
$tmp->statchange(2, -11"[from] intimidate|[of] %fslot({$this->U})");
     }
   break;

   case 
46// Pressure
    
$this->O("%n is exerting its pressure!","|-ability|%fslot|%ab");
   break;

   case 
104// Mold Breaker
   
case 163// Turboblaze
   
case 164// Teravolt
    
$this->O("%n breaks the mold!","|-ability|%fslot|%ab");
   break;

   case 
127// Unnerve
    
$n $GLOBALS['players'][1-($this->player%2)]->name;
    
$this->O("%n 's Unnerve makes $n's team too nervous to eat Berries!","|-ability|%fslot|%ab|$n");
   break;

   case 
119// Frisk
    
if($pk $this->randop(1))
     
$this->O("%n frisked the opponents and found one %item({$pk->item})!","|-item|%fslot({$pk->U})|%item({$pk->item})|[from] Frisk|[of] %fslot");
   break;

   case 
108// Forewarn
    
global $MOVES;
    
$pool = array(); $max=0;

    foreach(
$this->params['opponents'] as $o)
    if(
$o->hp)
     foreach(
$o->moves as $m)
      if(
$MOVES[$m]['bp']>$max)
      {
       
$pool = array(array($o,$m));
       
$max $MOVES[$m]['bp'];
      }
      else if(
$MOVES[$m]['bp']==$max)
       
$pool[]=array($o,$m);

    if(
$c=count($pool))
    {
     list(
$o,$m) = $pool[$BV->rand($c)];
     
$this->O("%n foresaw %pkn({$o->nick})'s %m($m)!","|raw|%n foresaw %pkn({$o->nick})'s %m($m)!");
    }
   break;

   case 
2: case 70: case 45: case 117// Auto Weather
    
$tmp = array(117=>BVideo::W_HAIL2=>BVideo::W_RAIN70=>BVideo::W_SUN45=>BVideo::W_SAND);
    
$BV->setweather($tmp[$this->ability], 0$this->O("","ability: %ab|[of] %fslot",-1));
    
$tmp = array(117=>"summoned a hail storm"2=>"is making it rain"70=>"has intensified the sunlight"45=>"kicked up up a sandstorm");
    
$this->O("%n's %ab {$tmp[$this->ability]}.","");
   break;

   case 
13: case 76// Cloud Nine, Air Lock
    
$this->O("%n's %ab clears the sky.","|-activate|%fslot|ability: %ab");
   break;
  }
 }

 function 
setability($a$from="")
 {
  global 
$ABILITIES$LANG;

  
// Multitype
  
if($a == 121 || $this->ability == 121) return $this->fail();

  if(!isset(
$ABILITIES[$a]))
  {
   
$q mysql_query("SELECT name FROM abilities WHERE id='{$a}' AND lang='$LANG'");
   if(
$r mysql_fetch_array($q)) $ABILITIES[$a] = $r[0];
   else 
$ABILITIES[$a] = "None";
  }

  
$this->ability $a;
  
$this->O("%n's ability became %ab($a)!","|-ability|%fslot|%ab($a)".$from);
  
$this->triggerability();
 }

 function 
checkitem($launcher false)
 {
  
$this->berrycheck($launcher);

  if(
$launcher)
  switch(
$this->item)
  {
   case 
29// Max Revive
    
$hp 100; goto revive;
   case 
28// Revive
    
$hp 50;
    
revive:
    if(!
$this->hp)
    {
     
$this->changehp($hp11);
     
$this->status 0;
     
$this->resetvolatile();
    }
   break;
   case 
17// Potion
    
$a 20$pc=0; goto _potion;
   case 
23// Full Restore
    
$this->setstatus(01);
    
$a 100$pc 1; goto _potion;
   case 
24// Max Potion
    
$a 100$pc 1; goto _potion;
   case 
26// Super Potion
    
$a 50$pc 0; goto _potion;
   case 
33// Moomoo milk
    
$a 100$pc 0; goto _potion;
   case 
25// Hyper Potion
    
$a 200$pc=0; goto _potion;
    
_potion:
     if(!
$this->hp$this->fail();
     else 
$this->changehp($a,$pc);
   break;
   case 
56// Dire Hit
    
$a 1; goto _direHit;
   case 
592// Dire Hit 2
    
$a 2; goto _direHit;
   case 
615// Dire Hit 3
    
$a 3_direHit:
    
$this->critlevel += $a;
   case 
57// X Attack
    
$s 1$a 1; goto _xstat;
   case 
597// X Attack 2
    
$s 1$a 2; goto _xstat;
   case 
603// X Attack 3
    
$s 1$a 3; goto _xstat;
   case 
609// X Attack 6
    
$s 1$a 6; goto _xstat;
   case 
58// X Defend
    
$s 2$a 1; goto _xstat;
   case 
596// X Defend 2
    
$s 2$a 2; goto _xstat;
   case 
602// X Defend 3
    
$s 2$a 3; goto _xstat;
   case 
608// X Defend 6
    
$s 2$a 6; goto _xstat;
   case 
61// X Special
    
$s 3$a 1; goto _xstat;
   case 
594// X Special 2
    
$s 3$a 2; goto _xstat;
   case 
600// X Special 3
    
$s 3$a 3; goto _xstat;
   case 
606// X Special 6
    
$s 3$a 6; goto _xstat;
   case 
62// X Sp. Def
    
$s 4$a 1; goto _xstat;
   case 
595// X Sp. Def 2
    
$s 4$a 2; goto _xstat;
   case 
601// X Sp. Def 3
    
$s 4$a 3; goto _xstat;
   case 
607// X Sp. Def 6
    
$s 4$a 6; goto _xstat;
   case 
59// X Speed
    
$s 5$a 1; goto _xstat;
   case 
593// X Speed
    
$s 5$a 2; goto _xstat;
   case 
599// X Speed
    
$s 5$a 3; goto _xstat;
   case 
605// X Speed
    
$s 5$a 6; goto _xstat;
    
_xstat$this->statchange($s+1$a);
   break;
   case 
611// Ability Urge
    
$this->triggerability();
   break;
   case 
614// Reset Urge
    
$this->statups = array(0,0,0,0,0,0,0);
   break;
  }

  switch(
$this->getitem())
  {
   case 
214// White Herb
    
$l = array();
    foreach(
$this->statups as $i=>$s)
     if(
$s 0$l[] = $i;
    if(
count($l) || $launcher)
    {
     foreach(
$l as $i$this->statups[$i] = 0;
     
$this->O("%n's White Herb restored its lowered stats.","|-clearboost|%fslot|[silent]");
     
$this->useitem();
    }
   break;
   case 
219// Mental Herb
    
$mask self::F_TAUNTED self::F_INFATUATED self::F_ENCORE self::F_DISABLE self::F_TORMENT;
    if(
$this->volatile $mask || $launcher)
    {
     
$this->volatile &= ~$mask;
     
$this->tauntturns $this->encoreturns $this->disableturns 0;
     
$this->lover null;
     
$this->O("%n's Mental Herb cured its volatile status.","");
     
$this->useitem();
    }
   break;
  }
 }

 function 
resetmulti()
 {
  global 
$BV;
  if(
$this->mturns)
  {
   if(
$this->mturns==1)
   {
    
$this->params['confturns'] = $BV->rand(4)+2;
    
$this->setstatus(self::F_CONFUSED0);
   }
   
$this->mturns 0;
  }
 }

 function 
flinch()
 {
  if(
$this->mbability() == 39) return false// Inner Focus
  
$this->volatile2 |= self::F2_FLINCHED;
//  if($this->ability == 80) $this->statchange(6, 1, 0, "[from] steadfast|[of] %fslot"); // Steadfast
  
if($this->hp$this->O("%n flinched!","");
 }

 function 
fail($from="")
 {
  
$this->params['fail'] = true;
  
$this->O("But it failed!","|-fail|%fslot".($from?"|$from":''));
  return 
false;
 }

 function 
canloseitem($selfcaused=false)
 {
  global 
$ITEMS;
  if(!
$this->item) return 0;
  else if(
$this->ability == 121) return false// Multitype
  
else if($this->mbability() == 60 && !$selfcaused) return false// Sticky Hold
  
else if(strpos($ITEMS[$this->item]['name'],"Mail")) return false;
  else if(
$this->item == 112 && $this->dex == 487) return false;
  return 
$this->item;
 }

 function 
useitem($more="")
 {
  
// Unburden
  
if($this->ability == 84$this->unburden 1;

  
$this->lastitem $this->item;
  
$this->O("","|-enditem|%fslot|%item".($more?"|$more":''));
  
$this->item 0;
 }

 function 
getitem()
 {
  global 
$BV;

  
// Klutz, Magic Room
  
if($this->ability == 103 || $this->volatile self::F_EMBARGO || $BV->mrcount) return 0;
  return 
$this->item;
 }

 function 
getweight()
 {
  
$w $this->dexinfo['weight'];
  switch(
$this->mbability())
  {
   case 
134// Heavy Metal;
    
$w <<= 1;
   break;
   case 
135// Light Metal
    
$w >>= 1;
   break;
  }
  switch(
$this->getitem())
  {
   case 
539// Float Stone
    
$w >>= 1;
   break;
  }
  return (int)(
$w/10);
 }

 function 
changehp($amount$pc=false$force=false$fromc=false$rounding=0)
 {
  global 
$ITEMS$BV$players;
  
$oldhp $this->hp;

  
// Magic Guard
  
if($this->ability == 98 && $pc && $amount<&& !$force) return 0;
  if(
$this->volatile self::F_HEALBLOCK && $amount>0) return 0;

  if(
$pc>0)
  {
   
$ratio = (100/$amount);
   
$amount $this->bstats[1]/$ratio;

   
// 489454568308 @ 21 (rain dish / leftovers truncated)
   // Roost / Revover like rounded up (54-24021-37159 @ 5)
   // 739875509625&@10 Moonlight rounded down
   
$amount $rounding
    
? ($rounding round($amount,0) : (int)$amount)
    : (
$amount <= ceil($amount) : ($ratio <= round($amount,0) : (int)$amount));

   
$amount *= $pc;
   if(!
$amount$amount $ratio>: -1;
  }

  
$confdmg = isset($this->params['move']) && !$this->params['move'];
  if((
$this->subhp && !$confdmg) && $amount<&& !$pc)
  {
   if(
abs($amount) >= $this->subhp)
    
$this->O("%n's substitute faded.","|-end|%fslot|Substitute");
   else
    
$this->O("%n's substitute took the damage.","|-start|%fslot|substitute|[damage]");

   
$oldshp $this->subhp;
   
$this->subhp max(0$this->subhp+$amount);
   
$subdmg $this->subhp abs($amount) : $oldshp;
   
BVideo::debug("Substitute damage $oldshp->{$this->subhp}");
  }
  else 
$this->hp max(0min($this->hp+$amount$this->bstats[1]));
//  if($oldhp==$this->hp) return 0;

  // False Swipe
  
if(!$pc && !$this->hp && isset($this->params['move']) && $this->params['move']==206$this->hp 1;
  if(
$this->volatile2 self::F2_ENDURE$this->hp 1;

  
// Sturdy
  
$sturdy $this->mbability()==5;
  if(!
$pc && $oldhp == $this->bstats[1] && ($this->getitem() == 275 || $sturdy) && !$this->hp)
  {
   
$this->hp 1;
   if(!
$sturdy$this->useitem();
   
$this->O("%n hung on with ".($sturdy?"sturdy":"its focus sash")."!",$sturdy?"|-activate|%fslot|Sturdy":"");
  }

  if(!
$pc && !$this->hp && $this->getitem() == 230// Focus Band
  
{
   if(
$BV->rand(100)<10)
   {
    
$this->hp 1;
    
$this->O("%n hung on with its focus band!","|-enditem|%fslot|%item");
   }
  }

  
$oldpc ceil(100*$oldhp/$this->bstats[1]);
  
$newpc ceil(100*$this->hp/$this->bstats[1]);
  
$omore = ($oldpc==" hpf" : ($oldpc <= 20 " hpr" : ($oldpc <= 50 " hpo" "")));
  
$nmore = ($newpc==" hpf" : ($newpc <= 20 " hpr" : ($newpc <= 50 " hpo" "")));

  if(
$oldhp != $this->hp)
  {
   
$this->O("<img src=\"{$this->icon}\" class=\"hpbari\" alt=\"\"> <span class=\"hpbar$omore\" style=\"background-size:{$oldpc}px 100%;\">&nbsp;$oldhp</span> &rarr; <span class=\"hpbar$nmore\" style=\"background-size:{$newpc}px 100%;\">&nbsp;{$this->hp}</span><br />","",1);
   
$this->O("","|-".($fromc=="painsplit"?"sethp":($oldpc<$newpc?"heal":"damage"))."|%fslot|".floor(abs($newpc-$oldpc))." (%hpc)".($fromc?"|[from] $fromc":""));
  }

  if(!
$this->hp && $this->status != self::S_FAINTED)
  {
   
$this->status self::S_FAINTED;
   
$this->resetvolatile();
   
$players[$this->player]->hasfainted[0] = true;
   
$BV->trigger(BVideo::E_FAINT); // To keep scores
   
$this->trigger(self::E_FAINTED$this->params);
   
$this->O("%n fainted!","|faint|%fslot");
   return 
$oldhp;
  }

  
$this->checkitem();
  return isset(
$subdmg) ? $subdmg : ($oldhp-$this->hp);
 }

 function 
hpberry($amount$rel)
 {
  global 
$ITEMS;

  
$x $this->item$this->item 0;
  if(
$this->changehp($amount$rel))
   
$this->O("%n's %item($x) restored some HP.","");
  
$this->item $x;

  
$this->useitem("[eat]");
 }

 function 
statusberry($s)
 {
  global 
$ITEMS;
  if((!
$s && $this->status) || ($s && $this->status == $s))
  {
   
$this->O("%n's %item clears its status problem.","");
   
$this->useitem("[eat]");
   
$this->setstatus(0,1);
  }

  if((!
$s || $s==-1) && $this->volatile self::F_CONFUSED)
  {
   
$this->volatile &= ~self::F_CONFUSED;
   
$this->O("%n's %item snapped it out of its confusion.","|-end|%fslot|confusion");
   
$this->useitem("[eat]");
  } 
 }

 function 
berrycheck($launcher false)
 {
  global 
$BV;

  if(isset(
$this->params['opponents']) && !$launcher)
  {
   foreach(
array_merge($this->params['opponents'],$this->params['allies']) as $o)
    if(
$o->ability == 127 && $o->player%2!=$this->player%&& $o->hp && $o->onfield// Unnerve
     
return;
  }
  
$s = ($this->ability == 82 2); // Gluttony
  
$quarter = ($this->hp <= $this->bstats[1]>>$s) || $launcher;
  
$half = ($this->hp <= $this->bstats[1]>>1) || $launcher;

  switch(
$iid $launcher $this->item $this->getitem())
  {
   case 
208// Enigma
    
if(isset($this->params['supereffective']))
    {
     
$this->hpberry(251);
     unset(
$this->params['supereffective']);
    }
   break;
   case 
158// Sitrus
    
if($half$this->hpberry(251);
   break;
   case 
155// Oran
    
if($half$this->hpberry(100);
   break;
   case 
43// Berry Juice
    
if($half$this->hpberry(200);
   break;
   case 
201// Liechi
    
$stat 1; goto pinchStat;
   case 
202// Ganlon
    
$stat 2; goto pinchStat;
   case 
203// Salac
    
$stat 5; goto pinchStat;
   case 
204// Petaya
    
$stat 3; goto pinchStat;
   case 
205// Apicot
    
$stat 4;

    
pinchStat:
    if(
$quarter)
    {
     
$this->O("%n ate its pinch berry!","");
     
$this->statchange($stat+110"item: %item($iid)");
     
$this->useitem();
    }
   break;
   case 
206// Lansat Berry
    
if($quarter)
    {
     
$this->critlevel+=2;
     
$this->O("%n ate its %item!","");
     
$this->useitem();
    }
   break;
   case 
157// Lum Berry
    
$this->statusberry(0);
   break;
   case 
149// Cheri Berry
    
$this->statusberry(self::S_PARALYZED);
   break;
   case 
150// Chesto Berry
    
$this->statusberry(self::S_ASLEEP);
   break;
   case 
151// Pecha Berry
    
$this->statusberry(self::S_POISON);
   break;
   case 
152// Rawst Berry
    
$this->statusberry(self::S_BURNED);
   break;
   case 
156// Persim Berry
    
$this->statusberry(-1);
   break;
   case 
207// Starf Berry
    
if($quarter)
    {
     
$pool range(0,4);
     foreach(
$pool as $i=>$stat)
      if(
$this->statups[$stat]==6) unset($pool[$i]);

     if(
count($pool))
     {
      
$stat $pool[$BV->rand(count($pool))];
      
$this->O("%n ate its %item!","");
      
$this->statchange($stat+120"item: %item($iid)");
      
$this->useitem();
     }
    }
   break;
  }
 }

 function 
type_mul($atype)
 {
  global 
$TE$BV;

  
$t1 $this->type1;
  
$t2 $this->type2;

  if(
$this->volatile2 self::F2_GROUNDED)
  {
   if(
$t1 == 3){ if(!$t2$t1 1; else {$t1 $t2$t2 0; }}
   else if(
$t2 == 3$t2 0;
  }

  
$t1 $TE[$atype][$t1];
  
$t2 = ($t2 $TE[$atype][$t2] : 1);

  if(
$atype == 5)
  {
   
// Ingrain, Gravity, Smack Down
   
$grounded $this->grounded || ($this->volatile2 self::F2_GROUNDED)
    || 
$BV->gravityt || $this->getitem()==278 || ($this->volatile self::F_INGRAIN);

   
// Levitate
   // Air Balloon
   
if((($this->mbability() == 26) || $this->getitem() == 541
     
|| ($this->volatile self::F_MAGNETRISE)) && !$grounded)
   {
    return 
0;
   }
   if(
$grounded && !($t1*$t2)) return max($t1$t2);
  }
  
// Scrappy
  
else if(($atype==|| $atype == 2) && !($t1*$t2)
   && (
$this->params['user']->ability == 113 || $this->volatile self::F_NOIMMUNITY))
  {
   return 
max($t1,$t2);
  }

  if(!(
$t1*$t2) && $this->getitem() == 543) return 1;
  return 
$t1*$t2;
 }

 function 
facingop()
 {
  global 
$BV$log$players$partys;
  if(
$BV->pc == 4)
  {
   
$pl = ($this->player+1)%4;
   if(
$pk $players[$pl]->party[$partys[$pl][0]])
    return 
$pk;
   else if(
$pk $players[$pl=($pl+2)%4]->party[$partys[$pl][0]])
    return 
$pk;
   else return 
false;
  }
  else
  {
   
$pl 1-$this->player;
   
$pos array_search($this->id,$partys[$this->player]);
   
$ct array_reverse(range(0,$log->leads-1));

   while(!(
$pk=$players[$pl]->party[$partys[$pl][$ct[$pos]]]) && $pk->hp)
    
$pos = ($pos+1)%count($ct);
   if(
$pk && $pk->hp) return $pk;
  }
  return 
false;
 }

 function 
randop($single=false)
 {
  global 
$BV$log$players$partys;

  if(
$BV->pc == 4)
   
// Invert==3 219179805159@11 trace
   // Invert==2 149738465902@0 frisk
   
$pl = ($this->player+($log->invert==3?1:3)+2*$BV->rand(2))%4;
  else
   
$pl 1-$this->player;

  
$pool = array();
  for(
$i=0$i<$log->leads$i++)
  {
   
$pk $players[$pl]->party[$partys[$pl][$i]];
   if(
$pk->hp$pool[]=$pk;
  }

  
// 471490498910&@1 Frisk rand
  // Trace: no rand
  
if(count($pool)>|| ($single && count($pool))) return $pool[$BV->rand(count($pool))];
  else if(
count($pool)==1) return $pool[0];
  else return 
false;
 }

 function 
resetvolatile()
 {
  
$this->subhp 0;
  
$this->critlevel 0;
  
$this->stockpile 0;
  
$this->protectcount 0;
  
$this->perishcount 0;
  
$this->quickclaw 2;
  
$this->unburden 0;
  
$this->hurtby = array();
  
$this->switching 0;
  
$this->mcharge 0;
  
$this->mturns 0;
  
$this->confturns 0;
  
$this->tauntturns 0;
  
$this->trapturns 0;
  
$this->encoreturns 0;
  
$this->disableturns 0;
  
$this->disabled 0;
  
$this->sleepcount $this->sleepturns;
  
$this->ability $this->oability;
  
$this->form $this->oform;
  
$this->bstats $this->obstats;
  
$this->grounded 0;
  
$this->history = array();
  
$this->hhistory = array();
  
$this->shistory = array();
  
$this->volatile 0;
  
$this->volatile2 0;
  
$this->type1 $this->dexinfo['type1'];
  
$this->type2 $this->dexinfo['type2'];
 }

 function 
effectswitch()
 {
  global 
$tn$partys$players$log$BV;

  
$i=0; foreach($players[$this->player]->party as $id=>$pk)
  if(
$id != $this->id && $pk->hp && !$pk->onfield$i++;
  if(!
$i || !count($log->switchins[$tn])) return false;

  for(
$pool=array(),$i=0$i $BV->pc$i++)
   
$pool[] = array_shift($log->switchins[$tn]);

  
$log->switchins[$tn] = array_merge($log->switchins[$tn]);
  
$id array_search($this->id$partys[$this->player]);

  foreach(
$pool as $s)
  {
   if(
$s[0]==$this->player && $s[4] == $id)
   {
    
$params = array("uturn"=>1);

    
// TODO TODO TODO 14-81671-03780
    // Bad design here - having to rollback the switch stack in case
    // the Pokemon switching out is killed by Pursuit.
    // This probably is buggy in some cases - Pursuit check should be
    // performed before reading the switch stack
    
if(!switchin(4$s[0], $s[3], $s[4], $params))
    {
     foreach(
$pool as $tmparray_unshift($log->switchins[$tn],$tmp);
     
$log->switchins[$tn] = array_merge($log->switchins[$tn]);
    }

    return 
true;
   }
  }

  return 
false;
 }

 function 
trigger($event, &$params)
 {
  global 
$BV$MOVES$META$partys$players$log$ITEMS$ABILITIES;

  
$affected false;
  
$this->params = &$params;

  switch(
$event)
  {
   case 
self::E_TURNSTART:
    switch(
$this->getitem())
    {
     case 
217// Quick Claw
      // 875735430109 No quick claw roll if no attack planned
      
if($this->planned[2] != BattleLog::P_ATTACK) break;
      
$r $BV->rand(100);
      if(
$r<20)
      {
       
$this->quickclaw++;
       
$this->O("%n's %item activated!","|-activate|%fslot|%item");
      }
     break;
     case 
210// Custap Berry
      
if(4*$this->hp <= $this->bstats[1])
      {
       
$this->O("%n's %item lets it move first!","|-activate|%fslot|custapberry");
       
$this->quickclaw++; 
       
$this->useitem();
      }
     break;
     case 
279: case 316// Lagging Tail / Full Incense
      
$this->quickclaw--;
     break;
    }
    if(
$this->ability == 100$this->quickclaw--; // Stall
   
break;

   case 
self::E_SWITCHOUT:
    
$this->onfield 0;
    
$this->bstats $this->obstats;
    
$this->statups = array(0,0,0,0,0,0,0);

    switch(
$this->ability)
    {
     case 
144// Regenerator
      
if($this->hp)
      {
       if(
$this->changehp(100/310"[silent]"))
        if(
$GLOBALS['JSOUT']) array_pop($GLOBALS['JS']); // Regenerator is internally handled
      
}
     break;

     case 
127// Unnerve
      
if(isset($this->params['opponents']) && is_array($this->params['opponents']))
      {
       foreach(
$this->params['opponents'] as $o)
        if(
$o->hp$o->berrycheck();
      }
     break;

     case 
30// Natural Cure
      
if($this->hp)
       
$this->setstatus(self::S_NONE,1"[silent]");
     break;
    }
   break;

   case 
self::E_SENDOUT:
    
$this->onfield 1;
    
$this->hasmoved 0;

    if(isset(
$params['batonpass']))
    {
     
$this->turncount = -1;
     goto 
postInitSwitch;
    }

    
$this->turncount = isset($params['replacement']) ? -0;
    
$this->toxiccount = ($this->toxiccount 0);
    
$this->resetvolatile();

    
postInitSwitch:
    
$t $GLOBALS['TE'][6][$this->type1];
    
$t *= (($tmp=$this->type2) ? $GLOBALS['TE'][6][$tmp] : 1);

    
// Damn workaround for initializing the structure without
    // triggering switch-in effects for #2 and #3 in rotation
    
if(isset($params['initial']) && $params['initial'] && $BV->rotation && $this->id) return;

    
// Healing Wish
    
if($BV->hwish[$this->player])
    {
     
$this->changehp(1001);
     
$this->status 0;
     
$BV->hwish[$this->player]--;
    }

    
// Stealth Rocks
    
if($BV->sidee[$this->player%2] & BVideo::S_ROCKS)
    {
     
$this->O("Pointed rocks dug into %n.","");
     
$this->changehp(-12.5*$t10"Stealth Rock");
     if(!
$this->hp) return;
    }

    
// Spikes
    
if(($BV->sidee[$this->player%2] & BVideo::S_SPIKES1) && $this->type_mul(5))
    {
     
$d 12.5;
     if(
$BV->sidee[$this->player%2] & BVideo::S_SPIKES2$d 16.666;
     if(
$BV->sidee[$this->player%2] & BVideo::S_SPIKES3$d 25;

     
$this->O("%n is hurt by spikes.","");
     
$this->changehp(-1*$d10"Spikes");
     if(!
$this->hp) return;
    }

    
// Toxic Spikes
    
if($BV->sidee[$this->player%2] & BVideo::S_TSPIKES1 && $this->type_mul(4) && $this->type_mul(5))
    {
     if(
in_array(4, array($this->type1$this->type2)))
     {
      
$this->O("%n absorbed the toxic spikes.","");

      if(
$BV->sidee[$this->player%2] & BVideo::S_TSPIKES1)
       
$this->O("","|-sideend|%p|Toxic Spikes");
      
$BV->sidee[$this->player%2] &= ~(BVideo::S_TSPIKES1 BVideo::S_TSPIKES2);
     }
     else
     {
      
$s self::S_POISON;
      if(
$BV->sidee[$this->player%2] & BVideo::S_TSPIKES2$s self::S_TOXIC;
      
$this->O("%n is poisoned by toxic spikes.","");
      
$this->setstatus($s1);
     }
    }

    
$tmp = array(298=>10299=>11300=>13301=>12302=>15303=>2304=>4305=>5306=>3307=>14308=>7309=>6310=>8311=>16312=>17313=>9);
    if(
$this->ability == 121 && isset($tmp[$this->getitem()])) // Multitype
    
{
     
$this->type1 $tmp[$this->getitem()];
     
$this->type2 0;
    }

    switch(
$this->getitem())
    {
     case 
541// Air Balloon
      
$this->O("%n is floating on a balloon.","|-item|%fslot|Air Balloon");
     break;
    }

    
$this->triggerability();
    
$BV->weffects();
   break;

   case 
self::E_WEATHER:
    if(
$this->ability == 142) return; // Overcoat

    
switch($BV->getweather())
    {
     case 
BVideo::W_RAIN:
      
$heal 0;
      if(
$this->ability == 44$heal 6.25// Rain Dish
      
else if($this->ability == 87$heal 12.5// Dry Skin

      
if($heal)
      {
       
$this->O("%n restored some HP from the rain.","");
       
$this->changehp($heal10"ability: %ab");
      }
     break;
     case 
BVideo::W_SUN:
      
$heal 0;
      if(
$this->ability == 87$heal = -12.5// Dry Skin
      
else if($this->ability == 94$heal = -12.5// Solar Power

      
if($heal)
      {
       
$this->O("%n ".($heal>0?'restored':'lost')." some HP from the sun.","");
       
$this->changehp($heal10"ability: %ab");
       if(!
$this->hp) return;
      }
     break;
     case 
BVideo::W_SAND:
      if(
in_array($this->ability, array(8,146,159))) return;
      else if(!
count(array_intersect(array($this->type1,$this->type2),array(5,6,9))))
      {
       
$this->O("%n is buffeted by the sandstorm!","");
       
$this->changehp(-6.25,10"Sandstorm");
       if(!
$this->hp) return;
      }
     break;
     case 
BVideo::W_HAIL:
      if(
$this->ability == 115)
      {
       
$this->O("%n restored some HP from the hail.","");
       
$this->changehp(6.25,10"Hail");
      }
      else if(
$this->ability == 81) return;
      else if(
$this->type1 != 15 && $this->type2 != 15)
      {
       
$this->O("%n is buffeted by the hail!","");
       
$this->changehp(-6.25,10"Hail");
       if(!
$this->hp) return;
      }
     break;
    }
   break;

   case 
self::E_TURNEND:
    
$this->turncount++;

    
// TODO Why the fuck are some effects activated on replacements
    
if(!$this->turncount) return;

    if(
$this->volatile2 & (self::F2_PROTECT|self::F2_WIDEGUARD|self::F2_QUICKGUARD|self::F2_ENDURE)) $this->protectcount++;
    else 
$this->protectcount 0;

    
$yawn $this->volatile2 self::F2_YAWN1;
    if((
$this->volatile2 self::F2_YAWN2) && !$this->status)
    {
     
$this->setstatus(self::S_ASLEEP1);
     
$this->volatile &= ~self::F_YAWN;
    }

    if(
$this->volatile self::F_HEALBLOCK && !--$this->hbturns)
     
$this->volatile &= ~self::F_HEALBLOCK;

    
$this->volatile2 self::F2_NONE;
    
$this->quickclaw 2;
    
$this->hurtby = array();
    
$this->hasmoved 0;
    if(
$this->mindread$this->mindread--;

    if(
$yawn$this->volatile2 |= self::F2_YAWN2;
    if(
$this->trapper && !($this->trapper->onfield && $this->trapper->hp))
     
$this->trapturns 0;
    if(
$this->trapturns)
    {
     if(!
$this->subhp)
     {
      
$this->O("%n is trapped and lost some health.","");
      
$this->changehp(-($this->trapper->getitem()==544 12.5 6.25), 1);
     }
     
$this->trapturns--;
     if(!
$this->hp) return;
    }
    if(!
$this->trapturns){ $this->volatile &= ~(self::F_TRAPPED); $this->trapper null; }

    if(
$this->tauntturns)
    {
     if(!--
$this->tauntturns)
     {
      
$this->volatile &= ~self::F_TAUNTED;
      
$this->O("%n's taunt wore off.","|-end|%fslot|taunt");
     }
    }

    if(
$this->encoreturns)
    {
     if(!--
$this->encoreturns)
     {
      
$this->volatile &= ~self::F_ENCORE;
      
$this->O("%n's encore ended.","|-end|%fslot|encore");
     }
    }

    if(
$this->disableturns)
    {
     if(!--
$this->disableturns)
     {
      
$this->volatile &= ~self::F_DISABLE;
      
$this->O("%n is no longer disabled.","|-end|%fslot|disable");
     }
    }

    if(
$this->volatile self::F_NIGHTMARE)
    {
     if(
$this->status == self::S_ASLEEP)
     {
      
$this->O("%n is locked in a nightmare!","");
      
$this->changehp(-2510"nightmare");
     }
     else
     {
      
$this->volatile &= ~self::F_NIGHTMARE;
      
$this->O("","|-end|%fslot|nightmare");
     }
    }

    
// Ingrain
    
if($this->volatile self::F_INGRAIN)
    {
     
$this->O("%n is absorbing health from its roots.","");
     
$r $this->getitem() == 296 8.125 6.25// Big Root
     
$this->changehp($r10"ingrain");
    }

    
// Aqua Ring
    
if($this->volatile self::F_AQUARING)
    {
     
$this->O("%n's health is restored by the aqua ring.","");
     
$r $this->getitem() == 296 8.333 6.25// Big Root
     
$this->changehp($r1,0"aquaring");
    }

    
// Curse
    
if($this->volatile self::F_CURSE)
    {
     
$this->O("%n is afflicted by the curse.","");
     
$this->changehp(-251);
     if(!
$this->hp) return;
    }

    
// Charge
    
if($this->volatile self::F_CHARGE && end($this->history)!=268)
     
$this->volatile &= ~self::F_CHARGE;

    switch(
$this->ability)
    {
     case 
139// Harvest
      
if(!$this->item && $this->lastitem && strpos($ITEMS[$this->lastitem]['name'], "Berry"))
      {
       if(
$BV->getweather() == BVideo::W_SUN || $BV->rand(100)<50)
       {
        
$this->O("%n harvested one %item({$this->lastitem}).","|-item|%fslot|%item({$this->lastitem})");
        
$this->item $this->lastitem;
        
$this->checkitem();
       }
      }
     break;
     case 
131// Healer
      
for($i=0$i<$log->leads$i++)
      {
       if(
$i == $this->slot) continue;
       if((
$a=$players[$this->player]->party[$partys[$this->player][$i]])
        && 
$a->hp && $a->status && $BV->rand(100)<30)
        
$a->setstatus(01"Healer|[of] %fslot({$this->U})");
      }
     break;
     case 
3// Speed Boost
      
$this->O("%n's %ab increases its speed!","|-activate|%fslot|speedboost");
      
$this->statchange(6,1,0,"[from] speedbost|[of] %fslot");
     break;
     case 
93// Hydration
      
if($this->status && $BV->getweather() == BVideo::W_RAIN)
       
$this->setstatus(01);
     break;
     case 
123// Bad Dreams
      
foreach($GLOBALS['SCACHE'] as $t)
      {
       if(
$t->player%!= $this->player%&& $t->status == self::S_ASLEEP)
       {
        if(
$dmg $t->changehp(-12.510"baddreams"))
         
$this->O("%pkn({$t->U}) lost $dmg HP due to %n's %ab.","");
       }
      }
     break;
     case 
141// Moody
      
$pool = array();
      foreach(
range(1,7) as $u)
      {
       if(
$this->statups[$u-1]==6) continue;
       foreach(
range(1,7) as $d)
        if(
$u != $d$pool[] = array($u,$d);
      }
      if(
$n=count($pool))
      {
       
$r $pool[$BV->rand($n)];
       
$this->statchange(1+$r[0], 2);
       
$this->statchange(1+$r[1], -1);
      }
     break;
     case 
61// Shed Skin
      
if($this->status && $BV->rand(100) <= 32)
      {
       
$this->O("%n's Shed Skin cured its status problem!","");
       
$this->setstatus(0,1,"[from] ability: %ab|[of] %fslot");
      }
     break;
     case 
161// Zen Mode
      
$h $this->getstat(0,1);
      if((
$h 50)^($this->form) && $this->dex == 555)
       
$this->formchange(1-$this->form);
     break;
    }
   break;

   case 
self::E_ITEMUPK:
    
### Item healing
    
$mul 1;
    switch(
$this->getitem())
    {
     case 
288// Sticky Barbs
      
$mul = -2;
     case 
281// Black Sludge
      
if($mul>&& !in_array(4, array($this->type1$this->type2))) $mul = -1;
     case 
234// Leftovers
      
if($mul<|| $this->getstat(0,1)<100)
       
$this->O("%n ".($mul>"restored some HP using its" "lost some health because of")." %item.","");
      
$this->changehp($mul*6.2510"item: %item");
     break;
    }
   break;

   case 
self::E_LEECHUPK:
    if(
$this->leecher$leecher $players[$this->leecher[0]]->party[$partys[$this->leecher[0]][$this->leecher[1]]];
    else 
$leecher null;

    if(
$this->volatile self::F_LEECHED && $leecher && $leecher->hp)
    {
     
$this->O("%n's health is leeched towards %pkn({$leecher->U}).","");
     
$r $this->changehp(-12.510"Leech Seed|[of] %fslot({$leecher->U})");

     
// Big Root
     
if($leecher->getitem() == 296$r = (int)(4*$r/3);
     if(
$this->ability == 64// Liquid Ooze
     
{
      
$r *= -1;
      
$this->O("%n's Liquid Ooze is hurting %pkn({$leecher->nick}).","");
     }
     
$leecher->changehp($r, -1);
     
$this->checkitem();
    }
   break;

   case 
self::E_STATUSUPK:
    switch(
$this->status)
    {
     case 
self::S_BURNED:
      
$this->O("%n was hurt by its burn.","");
      
$this->changehp(($this->ability==85 ? -6.25 : -12.5), 10"brn"); // Heatproof
      
if(!$this->hp) return;
     break;

     case 
self::S_POISON:
      
// Poison Heal
      
if($this->ability == 90)
      {
       
$this->O("%n is healed by poison.","");
       
$this->changehp(12.510"ability: Poison Heal");
      }
      else
      {
       
$this->O("%n was hurt by poison.","");

       if(!
$this->toxiccount)
        
$this->changehp(-12.510"psn");
       else
        
$this->changehp(-6.25$this->toxiccount++, 0"psn");

      }
     break;
    }
    
$this->checkitem();
   break;

   case 
self::E_FINALUPK:
    switch(
$this->getitem())
    {
     case 
273: case 272// Toxic Orb / Flame Orb
      
$tmp = array(273=>self::S_BURNED272=>self::S_TOXIC);
      if(!
$this->status && $this->turncount$this->setstatus($tmp[$this->getitem()], true);
     break;
    }

    if(
$this->volatile self::F_PERISH && $this->perishturns--) // Perish after leech seed/leftovers
    
{
     
$this->O("%n's perish counter went down to {$this->perishturns}!","|-start|%fslot|perish{$this->perishturns}");
     if(!
$this->perishturns)
     {
      
$this->changehp(-10011"move: Perish Song");
      return;
     }
    }
   break;

   case 
self::E_PREATTACK:
    
$this->volatile &= ~self::F_DESTINYBOND;
    if(
$this->hasmoved && !$params['reflected']){ $params['skip']=true; return false; }
    if(!
$params['reflected']) $this->hasmoved 1;

    
$mid $params['move'];

    
// Truant
    
if($this->ability == 54 && count($this->history) && end($this->history))
    {
     
$this->O("%n is loafing around.","|cant|%fslot|ability: Truant|%m");
     
$params['move'] = 0$params['skip'] = true; return false;
    }

    
// Main Sleep check - sleep counter
    
if($this->status == self::S_ASLEEP)
    {
     
$this->sleepcount--;
     if(
$this->ability == 48$this->sleepcount--; // Early Bird

     
if(!$this->sleepcount)
     {
      
$this->O("%n woke up!","");
      
$this->setstatus(01,"slp");
     }
     else if(
$mid != 173 && ($mid != 214 || count($this->moves)==1)) // Sleep Talk
     
{
      
$params['skip'] = true;
      
$this->O("%n is fast asleep.","|cant|%fslot|slp");
      return;
     }
    }

    
// Freeze status
    
if($this->status == self::S_FREEZE)
    {
     if(
$META[$mid]['flags'] & (1<<11) || ($BV->rand(100) < 20)) // Defrost flag
     
{
      
$this->setstatus(0,1,"frz");
      
$this->O("%n thawed!","");
     }
     else
     {
      
$this->O("%n is frozen solid.","|cant|%fslot|frz");
      
$params['skip'] = true;
      return;
     }
    }

    
// Flinch is after thaw and sleep (242077487794)
    
if($this->volatile2 self::F2_FLINCHED)
    {
     
$this->O("%n flinched and cannot use %m($mid).","|cant|%fslot|flinch");
     if(
$this->ability == 80$this->statchange(610"[from] steadfast|[of] %fslot"); // Steadfast
     
$params['skip'] = true; return;
    }

    
// Confusion: after sleep for Sleep Talk
    
if($this->volatile self::F_CONFUSED)
    {
     
$this->confturns--;
     if(!
$this->confturns)
     {
      
$this->O("%n snapped out of its confusion!","|-end|%fslot|confusion");
      
$this->volatile &= ~self::F_CONFUSED;
     }
     else
     {
      
$this->O("%n is confused!","|-activate|%fslot|confusion");
      
$r $BV->rand(100);
      if(
$r 50)
      {
       
$this->O("%n hurt itself in its confusion.","");
       
$params['targets'] = array($this);
       
$params['move'] = 0;
       return;
      }
     }
    }

    
// Sleep Talk and Snore
    
if($this->status == self::S_ASLEEP)
    {
     if(
$mid == 214 && count($this->moves)>1)
     {
      
$pool = array();
      foreach(
$this->moves as $m) if($m && $m != 214$pool[]=$m;
      
$m $pool[$BV->rand(count($pool))];
      
$this->O("%n's %m(214) allows it to use %m($m).","");
      
$a $this->planned$a[3] = $m;
      
do_action($a, array('mcalled'=>1));
      
$params['skip'] = true; return;
     }
    }

    
// Taunt before paralysis 628764403705
    
if($MOVES[$mid]['cat']==&& $this->volatile self::F_TAUNTED)
    {
     
$this->O("%n cannot use %m because of the taunt.","|cant|%fslot|move: Taunt|%m");
     
$params['skip'] = true; return false;
    }

    
// No Paralysis on self-targeted moves
    
if($this->status == self::S_PARALYZED)
    {
     if(
$BV->rand(100) < 25)
     {
      
$params['skip'] = true;
      
$this->O("%n is paralyzed and cannot use %m","|cant|%fslot|par");
      return;
     }
    }

    if(
$this->volatile self::F_INFATUATED)
    {
     
$lover $players[$this->lover[0]]->party[$this->lover[1]];
     if(
$lover->onfield)
     {
      
$r $BV->rand(100);
      if(
$r 50)
      {
       
$this->O("%n's love for %pkn({$lover->U}) prevents it from using %m.","|cant|%fslot|attract");
       
$params['skip'] = true;
       return 
false;
      }
      else 
$this->O("%n is in love with %pkn({$lover->U}).","|-activate|%fslot|attract|[of] %fslot({$lover->U})");
     }
     else
     {
      
$this->volatile &= ~self::F_INFATUATED;
      
$this->O("%n snapped out of his infatuation.","|-end|%fslot|attract");
     }
    }

    
// Imprison
    
foreach($params['opponents'] as $o)
    {
     if(
$o->volatile self::F_IMPRISON)
     {
      if(
in_array($mid$o->moves))
      {
       
$this->O("%pkn({$o->U}) has imprisoned %m","|cant|%fslot|move: Imprison|%m");
       
$params['skip'] = true; return false;
      }
     }
    }

    
// Torment
    
if($this->volatile self::F_TORMENT && !($this->volatile2 self::F2_NOTORMENT) && end($this->history)==$mid)
    {
     
$this->O("%n's torment prevents it from using %m again.","|cant|%fslot|move: Torment|%m");
     
$params['skip'] = true; return false;
    }

    
// Disable
    
if($this->volatile self::F_DISABLE && $this->disabled==$mid)
    {
     
$this->O("%n's %m is disabled.","|cant|%fslot|move: Disable|%m");
     
$params['skip'] = true; return false;
    }

    
// Mimic
    
if($mid == 102 && $this->mimic$params['move'] = $mid $this->mimic;
   break;

   case 
self::E_PREATTACK2:
    
$mid $params['move'];

    
// Wide Guard
    
if(count($params['targets'])>1)
    {
     foreach(
$params['targets'] as $tid=>$t)
     {
      if(
$t->volatile2 self::F2_WIDEGUARD)
      {
       if(
$t->player%== $this->player%2){ unset($params['targets'][$tid]); continue; }
       
$params['skip'] = true;
       
$this->O("%pkn({$t->U})'s Wide Guard prevents %n from using %m.","|-singleturn|%fslot|wideguard");
      }
     }
    }

    
// Having to repick target after para/confusion (78-50401-67211)
    // Related ASM: 21CAA78 (why is it called at that time? 21BE0DE/21BDFCC)
    
if($mid && $META[$mid]['target'] == 8)
    {
     
// Invert==0 378343458678@3 Outrage Invert==3 250849576832@5
     
if(count($params['targets'])>1)
     {
      
$t $BV->rand(count($params['targets']));
      
$params['targets'] = array($params['targets'][$t]);
     }
     else if(
count($params['targets']) && ($BV->pc>|| $log->leads>1))
     {
      
$BV->rand(2); // TODO
     
}
     
$params['tc'] = count($params['targets']);
    }

    
// Future Sight
    
if($mid == 248 && !isset($params['delayed']))
    {
     
$f false;
     foreach(
$GLOBALS['delayed'] as $d)
      if(
$d[0]==&& $d[1]==$this$f=true;

     if(!
$f)
     {
      
$this->O("","|move|%fslot|%m");
      
$this->O("%n foresaw an attack!","|-start|%fslot|futuresight");
      
$BV->lastmove 248;
      
$params['delay'] = true;
     }
     else{ 
$this->fail(); $params['skip'] = true; }
     return 
false;
    }

    
// Wish
    
if($mid == 273 && !isset($params['delayed']))
    {
     
$this->O("%n made a wish!","|move|%fslot|%m");
     
$params['delay'] = true; return false;
    }

    
// Locking moves, slightly bugged when mcalled 221888640056
    
if(isset($META[$mid]) && $META[$mid]['effect']==28 && !$this->mturns)
    {
     
$duration 2+$BV->rand(2); // Always roll duration
     
if(!isset($params['mcalled']))
     {
      
$this->mturns $duration;
      
$params['firstmturn'] = true;
      
BVideo::debug("Move duration: $duration turns.");
     }
    }

    
// Charge moves
    
if(isset($META[$mid]) && $META[$mid]['flags'] & (1<<2))
    {
     if(
$this->mcharge)
     {
      
$this->mcharge 0;
      
$this->params['nohistory'] = true;
     }
     else
     {
      
$this->O("%n is preparing to use %m.","|-prepare|%fslot|%m|%fslot({$params['targets'][0]->U})");

      if(
$mid == 76 && $BV->getweather() == BVideo::W_SUN)
      {
       
$this->O("There is no charging turn in Sunlight.","");
      }
      else if(
$this->getitem() == 271// Power Herb
      
{
       
$this->O("%n's Power Herb allows it to forego the the charging turn.","");
       
$this->useitem();
      }
      else
      {
       
$this->mcharge $mid;
       
$params['skip'] = $params['charge'] = true;
       return;
      }
     }
    }
   break;

   case 
self::E_AFFECTED:
    
$affected true;
   case 
self::E_ATTACK:
    
$user $params['user'];
    
$mid $params['move'];
    
$crit false;
    
$stab 0x1000;
    
$destinybond = ($this->volatile self::F_DESTINYBOND);

    if(!
$mid)
    {
     
$atype = -1;
     
$bp 40;
     
$tmul 1;
     
$sid 1;
     
$mod 0x1000;
     goto 
damageCalc;
    }

    
$atype $MOVES[$mid]['type'];
    
$bp $MOVES[$mid]['bp'];

    if(
$user->ability == 96$atype=1// Normalize

    // Variable type
    
switch($mid)
    {
     case 
237// Hidden Power
      
$atype $user->hpt;
     break;
     case 
449// Judgment
      
$jt = array(298=>10299=>11300=>13301=>12302=>15303=>2304=>4305=>5306=>3307=>14308=>7309=>6310=>8311=>16312=>17313=>9);
      if(isset(
$jt[$user->item])) $atype $jt[$user->item]; 
     break;
     case 
311// Weather Ball
      
switch($BV->getweather())
      {
       case 
BVideo::W_RAIN$atype 11; break;
       case 
BVideo::W_SUN$atype 10; break;
       case 
BVideo::W_SAND$atype 6; break;
       case 
BVideo::W_HAIL$atype 15; break;
      }
     break;
     case 
363// Natural Gift
      
$NG = array(149=>array(1060),150=>array(1160),151=>array(1360),152=>array(1260),153=>array(1560),154=>array(260),155=>array(460),156=>array(560),157=>array(360),158=>array(1460),159=>array(760),160=>array(660),161=>array(860),162=>array(1660),163=>array(1760),164=>array(960),165=>array(1070),166=>array(1170),167=>array(1370),168=>array(1270),169=>array(1570),170=>array(270),171=>array(470),172=>array(570),173=>array(370),174=>array(1470),175=>array(770),176=>array(670),177=>array(870),178=>array(1670),179=>array(1770),180=>array(970),181=>array(1080),182=>array(1180),183=>array(1380),184=>array(1060),185=>array(1160),186=>array(1360),187=>array(1260),188=>array(1560),189=>array(260),190=>array(460),191=>array(560),192=>array(360),193=>array(1460),194=>array(760),195=>array(660),196=>array(860),197=>array(1660),198=>array(1760),199=>array(960),200=>array(160),201=>array(1280),202=>array(1580),203=>array(280),204=>array(480),205=>array(580),206=>array(380),207=>array(1480),208=>array(780),209=>array(680),210=>array(880),211=>array(1680),212=>array(1780));
      if((
$i=$user->getitem()) && isset($NG[$i]))
       list(
$atype$bp) = $NG[$i];
      if(!
$affected$user->item 0;
     break;
    }

    
$tmul $this->type_mul($atype);
    if(
$tmul>1$this->params['supereffective'] = 1;
    
$this->hadsub = ($this->subhp 0);

    if(
$affected)
    {
     if(
$user->player == $this->player && $user->id == $this->id
       
&& $MOVES[$mid]['cat']==1) return !($params['fail']=0);

     
// Damp
     
if($META[$mid]['effect'] == 39 && in_array($this->mbability(),array(5,6)))
     {
      
$this->O("%n is protected by %ab!","|-activate|%fslot|%ab");
      return 
false;
     }

     switch(
$mid)
     {
      case 
363// Natural Gift
       
if(!(($a $user->getitem()) && strpos($ITEMS[$a]['name'],"Berry"))) return $this->fail();
      break;
      case 
264// Focus Punch
       
if(count($user->hurtby)) return $this->fail();
      break;
      case 
255// Spit Up
       
if(!$this->stockpile) return $this->fail();
      break;
      case 
387// Last Resort
       
foreach($user->moves as $m)
       {
        if(
$m == 387 || !$m) continue;
        foreach(
$user->history as $i=>$tmp)
         if(
$tmp == $m && $user->shistory[$i]) continue 2;
        return 
$this->fail();
       }
      break;
      case 
213// Attract
       
if((1-$this->gender) != $user->gender) return $this->fail();
      break;
      case 
283// Endeavour
       
if($user->hp $this->hp) return $this->fail();
      break;
      case 
382// Me First
       
if($this->hasmoved || !isset($this->planned) || $this->planned[2] != BattleLog::P_ATTACK)
        
$this->fail();
       else
       {
        
$user->hasmoved 0;
        
$a $user->planned;
        
$a[3] = $this->planned[3];
        
do_action($a, array('bpmul'=>0x1800'mefirst'));
       }
       return 
false;
      break;
      case 
389// Sucker Punch
       
if($this->planned[2] != BattleLog::P_ATTACK || $MOVES[$this->planned[3]]['cat']==|| $this->hasmoved)
        return 
$this->fail();
      break;
      case 
252// Fake Out
       
if(count($user->history) && $user->turncount) return $this->fail();
      break;
      case 
138// Dream Eater
       
if($this->status != self::S_ASLEEP) return $this->fail();
      break;
      case 
173// Snore
       
if($user->status != self::S_ASLEEP) return $this->fail();
      break;
      case 
102// Mimic
       
if(($lm end($this->history)) && !in_array($lm, array(448,118,102,166,165)))
       {
        
$user->mimic $lm;
        
$user->O("%n learned %m($lm)!","|-start|%fslot|mimic|%m($lm)");
       }
       else return 
$this->fail();
      break;
      case 
68// Counter
       
$at 2; goto _counterCheck;
      case 
243// Mirror Coat
       
$at 3; goto _counterCheck;
      case 
368// Metal Burst
       
$at 0;
       
_counterCheck:
       foreach(
$this->hurtby as $h)
       {
        if(
$h[2] && (!$at || $h[3]==$at) && ($h[0]%!= $this->player%2))
        {
         
$tpk $players[$h[0]]->party[$partys[$h[0]][$h[1]]];
         
$dmg = (int)($h[2] * ($at 1.5));

         if(
$user==$this)
         {
          
$params['xdmg'] = $dmg;
          
$params['tpk'] = $tpk;
         }
        }
       }
       if(!isset(
$params['tpk'])) return $this->fail();
       if(!
$tpk->type_mul($atype)) return $this->fail();
      break;
     }

     
// Immunity is before accuracy for damaging moves and Thunder Wave
     
if((!$tmul && ($MOVES[$mid]['cat']>|| $mid==86) && $mid != 165// Struggle ignores immunities
        
|| ($mid==171 && $this->status != self::S_ASLEEP))
     {
      
$this->O("%un's attack has no effect on %n...","|-immune|%fslot|[msg]");
      return 
false;
     }

     
// Gravity
     
if($BV->gravityt && ($META[$mid]['flags']>>10)&1)
     {
      
$this->O("%m be used during Gravity!","|cant|%fslot|gravity|%m");
      return 
false;
     }

     
$oor false;
     switch(
$this->mcharge)
     {
      case 
19// Fly
       
$x = array(165423274798723918); goto _flyBounce;
      case 
340// Bounce
       
$x = array(1687239327);
       
_flyBounce: if(!in_array($mid$x)) $oor=true;
       else 
chainmod($params['bpmul'],0x2000);
      break;
      case 
91// Dig
       
if(!in_array($mid, array(89,90,220))) $oor=true;
       else 
chainmod($params['bpmul'],0x2000);
      break;
      case 
291// Dive
       
if(!in_array($mid, array(57,250))) $oor=true;
       else 
chainmod($params['bpmul'],0x2000);
      break;
      case 
467// Shadow Force
       
$oor true;
      break;
     }

     if(
$oor && !$this->mindread)
     {
      
$this->O("%un is out of range.","|-miss|%fslot({$user->U})|%fslot");
      
// [from] move: %m({$this->mcharge})");
      
$this->fixmiss();
      return 
false;
     }

     if(
$this->volatile2 self::F2_PROTECT)
     {
      if(
$mid == 364// Feint
      
{
       
$this->volatile2 &= ~(self::F2_PROTECT self::F2_WIDEGUARD);
       
$this->O("The feint broke %n's guard!","|-activate|%fslot|feint");
      }
      else if(
in_array($mid, array(367,174,353,364,248,286,195,244,272,467,144)))
      {
       
// Not blocked
      
}
      else if(
$META[$mid]['flags'] & (1<<4))
      {
       
$this->O("%n protected itself!","|-activate|%fslot|Protect");
       return 
false;
      }
     }

     foreach(
$params['opponents'] as $p)
     {
      if(
$p->volatile2 self::F2_QUICKGUARD && $META[$mid]['priority']>0)
      {
       
$this->O("%n was protected by %pkn({$p->U})'s Quick Guard!","|-activate|%fslot|quickguard");
       return 
false;
      }
     }

     switch(
$this->mbability())
     {
      case 
43// Soundproof
       
if(($META[$mid]['flags']>>9)&1)
       {
        
$this->O("%n is immune because of %ab!","|-immune|%fslot|%ab");
        return 
false;
       }
      break;
      case 
10// Volt Absorb
       
if($atype == 13) goto _absorb;
      break;
      case 
87: case 11: if($atype != 11 || $MOVES[$mid]['cat']==1) break; // Water Absorb
       
_absorb:
       
$this->O("%n's HP is restored by %ab.","");
       
$this->changehp(25,10"ability: %ab");
       return 
false;
      break;
      case 
18// Flash Fire
       
if($atype==10)
       {
        
$this->O("%n's fire type moves are boosted by %ab","|-start|%fslot|flashfire");
        
$this->volatile |= self::F_FLASHFIRE;
        return 
false;
       }
      break;
      case 
114// Storm Drain
       
if($atype==11 && $MOVES[$mid]['cat']>1)
       {
        
$this->O("%n's Special Attack is boosted by %ab!","");
        
$this->statchange(410"[from] ability: %ab|[of] %fslot");
        return 
false;
       }
      break;
      case 
25// Wonder Guard
       
if($tmul<&& $MOVES[$mid]['cat']>1)
       {
        
$this->O("%n's %ab makes it immune to the attack!","|-activate|%fslot|wonderguard");
        return 
false;
       }
      break;
      case 
78// Motor Drive
       
if($MOVES[$mid]['cat']>&& $atype==13)
       {
        
$this->O("%n's %ab increased its Speed!","");
        
$this->statchange(610"[from] ability: %ab");
        return 
false;
       }
      break;
      case 
31// Lightningrod
       
if($atype==13)
       {
        
$this->O("%n's %ab increased its Special Attack!","");
        
$this->statchange(410"[from] ability: %ab");
        return 
false;
       }
      break;
      case 
157// Sap Sipper
       
if($atype==12)
       {
        
$this->O("%n's %ab increased its Attack!","");
        
$this->statchange(210"[from] ability: %ab");
        return 
false;
       }
      break;
      case 
140// Telepathy
       
if($user->player%== $this->player%2)
       {
        
$this->O("%n avoids its allies' attacks with %ab!","|-activate|%fslot|telepathy");
        return 
false;
       }
      break;
     }

     if(
$MOVES[$mid]['acc'])
     {
      
$acc $MOVES[$mid]['acc'];
      
$nocheck false;

      
// No Guard
      
if($user->ability == 99 || $this->ability == 99$nocheck true;
      
// Pursuit on switch
      
if(isset($params['pursuit'])) $nocheck true;
      if(
$this->mindread$nocheck true;

      switch(
$mid)
      {
       case 
59// Blizzard
        
if($BV->getweather() == BVideo::W_HAIL$nocheck true;
       break;
       case 
542: case 87// Thunder, Hurricane
        
if($BV->getweather() == BVideo::W_RAIN$nocheck true;
        else if(
$BV->getweather() == BVideo::W_SUN$acc=50;
       break;
      }

      if(!
$nocheck)
      {
       if(
$META[$mid]['effect'] != 39)
       {
        
// Zoom Lens
        
$amod = ($user->getitem()==276 && $this->hasmoved) ? 0x1333 0x1000;
        
$amod $user->getstat(60$amod);
        
$emod $this->getstat(7);

        
$acc round($acc*$amod/$emod,0); //ApplyAccuracyBoost
        
BVideo::debug("Modified accuracy: $acc {$user->nick}($amod)->{$this->nick}($emod).");
       }
       else
       {
        if(
$user->lvl $this->lvl) goto _immune;
        
$acc += $user->lvl-$this->lvl;
       }

       
$r $BV->rand(100);
       if(
$r >= $acc)
       {
        
$this->O("%n avoided %un's attack!","|-miss|%fslot({$user->U})|%fslot");

/*
        if(count($params['targets'])>1)
         $this->O("","|-miss|%fslot|[msg]");
        else
         $user->O("","|-miss|%fslot");
*/

        
$this->fixmiss();
        return 
false;
       }
      }
     }

     
// Immunity is after accuracy for Toxic
     
if(!$tmul && $mid==92)
     {
      
_immune:
      
$this->O("%un's attack has no effect on %n","|-immune|%fslot|[msg]");
      return 
false;
     }

     
// Substitute
     //$exc = array(213,174,194,50,227,193,288,385,114,391,286,357,316,195,244,46,272,285,180,269,259,18,270);
     
if($MOVES[$mid]['cat']==&& $this->subhp && !(($META[$mid]['flags']>>14)&1)) // Use substitute bypass flag
     
{
      
$this->O("The attack is blocked by %n's Substitute.","|-start|%fslot|substitute|[block]");
      return 
false;
     }

     
// Multi hit moves (after accuracy)
     
if($minh $META[$mid]['minhits'])
     {
      
$maxh $META[$mid]['maxhits'];

      if(
$maxh $minh)
      {
       
$r $BV->rand(100);
       
$ht = array(00357085100);
       for(
$minh=0$r >= $ht[$minh]; $minh++);
      }
      if(
$user->ability == 92// Skill Link
       
$minh $maxh;

      
// Beat Up
      
if($mid == 251)
      {
       
$pool = array();
       foreach(
$players[$user->player]->party as $pk)
        if(
$pk->hp && ($pk==$user || !$pk->status)) $pool[] = $pk;

       
$params['beatup'] = $pool;
       
$minh count($pool);
      }

      
BVideo::debug("Number of hits: $minh");
      
$params['hits'] = $minh;
     }

     
$params['fail'] = 0;
     return 
true;
    }

    
// OHKO Moves
    
if($META[$mid]['effect'] == 39)
    {
     
$this->O("It's a one-hit KO!","|-ohko");
     
$this->changehp(-($dmg=$this->bstats[1]), 0);
     
$this->hurtby[] = array($user->player$user->slot$dmg$MOVES[$mid]['cat'], $user->id);
     return;
    }

    
// Bypass accuracy when damage is set
    
if(isset($params['dmg']) && in_array($mid, array(68,243,368)))
    {
     
$dmg $params['dmg'];
     goto 
EndDmg;
    }

    
// Damaging moves
    
if($MOVES[$mid]['cat']>1)
    {
     
// Shell Armor, Battle Armor, Lucky Chant
     
if(!in_array($this->mbability(), array(475)) && !($BV->sidee[$this->player%2] & BVideo::S_LUCKYCHANT))
     {
      if(
$META[$mid]['effect']== 289)
      {
       
$crit 1;
      }
      else
      {
       
$crm $META[$mid]['critrate']; // Crit level
       
$crm += $user->critlevel;

       if(
$user->ability == 105$crm++; // Super Luck
       
switch($user->getitem())
       {
        case 
232: case 326// Scope Lens, Razor Claw
         
$crm++;
        break;
        case 
259// Stick
         
if($user->dex==83$crm+=2;
        break;
        case 
256// Lucky Punch
         
if($user->dex==113$crm+=2;
        break;
       }
       
$crl = array(168432);
       if(
$crm 4$crm 4;
       
$crit = ($BV->rand($crl[$crm])==0);
      }
     }

     switch(
$mid// Fixed damage
     
{
      case 
68// Counter
      
case 243// Mirror Coat
      
case 368// Metal Burst
       
$params['dmg'] = $params['xdmg'];
       
$params['tpk']->trigger(BPkm::E_ATTACK$params);
       return;
      break;
      case 
162// Super Fang
       
$dmg max($this->hp >> 1,1);
       goto 
EndDmg;
      break;
      case 
149// Psywave
       
$dmg max(1, (int)((($BV->rand(101)+50)*$user->lvl)/100));
       goto 
EndDmg;
      break;
      case 
101: case 69// Seismic Toss / Night Shade
       
$dmg $user->lvl;
       goto 
EndDmg;
      break;
      case 
49// Sonicboom
       
$dmg 20;
       goto 
EndDmg;
      break;
      case 
82// Dragon Rage
       
$dmg 40;
       goto 
EndDmg;
      break;
      case 
283// Endeavour
       
$dmg max(1$this->hp-$user->hp);
       goto 
EndDmg;
      break;
      case 
515// Final Gambit
       
$dmg $user->hp;
       
$user->changehp(-100,1,1);
       goto 
EndDmg;
      break;
      case 
280// Brick Break
       
if($BV->sidee[$this->player%2]&(BVideo::S_REFLECT|BVideo::S_LIGHTS))
       {
        
$this->O("The barrier around %n shattered!","|-activate|%fslot({$user->U})|brickbreak|[of] %fslot");
        
$BV->sidee[$this->player%2] &= ~(BVideo::S_REFLECT|BVideo::S_LIGHTS);
       }
      break;
      case 
165// Struggle
       
$tmul 1// Typeless damage
      
break;
     }

     if(
$params['gem'] > 1)
     {
      
$user->O("The power of %m($mid) is increased by %n's %item","|-enditem|%fslot|%item|[from] gem|[move] %m($mid)");
      
$params['gem'] = 1;
     }

     if(
$crit$this->O("","|-crit|%fslot");
     if(
$tmul!=1)
      
$this->O("It's ".($tmul<1?'not very':'super')." effective against %n.""|-".($tmul<1?"resisted":"supereffective")."|%fslot");

     
###### BASE POWER ######

     
switch($mid)
     {
      case 
228// Pursuit
       
if(isset($params['pursuit'])) $bp *= 2;
      break;
      case 
255// Spit Up
       
$bp 100*$this->stockpile;
       
$this->stockpile 0;
       
$this->statchange(3, -1); $this->statchange(5, -1);
      break;
      case 
514// Retaliate
       
$hasf $GLOBALS['players'][$user->player]->hasfainted;
       if(
$hasf[1] || $hasf[0]) $bp *= 2;
      break;
      case 
237// Hidden Power
       
$bp $user->hpp;
      break;
      case 
76// SolarBeam
       
if(($w=$BV->getweather()) && $w!=BVideo::W_SUN$bp >>=1;
      break;
      case 
512// Acrobatics
       
if(!$user->getitem() || $params['gem']) $bp *= 2;
      break;
      case 
500// Stored Power
       
foreach($user->statups as $s) if($s>0$bp += 20*$s;
      break;
      case 
216// Return
       
$bp max(1,(int)($user->happiness*10/25));
      break;
      case 
218// Frustration
       
$bp max(1, (int)((255-$user->happiness)*10/25));
      break;
      case 
372// Assurance
       
if(count($this->hurtby)) $bp *= 2;
      break;
      case 
419// Avalanche
      
case 279// Revenge
       // 267232308908 Onfield
       
foreach($user->hurtby as $pk)
       if(
$pk[0]==$this->player && /*$partys[$this->player][$pk[1]]*/ $pk[3] == $this->id)
       {
        
$bp *= 2; break;
       }
      break;
      case 
362// Brine
       
if($this->getstat(0,1) <= 50$bp *= 2;
      break;
      case 
462// Crush Grip
       
$bp 1+(int)(1.2*$this->getstat(0,1));
      break;
      case 
378: case 462// Wring Out, Crush Grip
       
$bp = (int)(120*$this->getstat(0,1)/100);
      break;
      case 
323: case 284// Eruption / Water Spout
      
$bp = (int)(150*$user->getstat(0,1)/100);
      break;
      case 
263// Facade
       
if($user->status$bp *= 2;
      break;
      case 
358// Wake-Up Slap
       
if($this->status == self::S_ASLEEP)
       {
        
$bp *= 2;
        
$this->O("%n woke up!","|-curestatus|%fslot|slp");
        
$this->status 0;
       }
      break;
      case 
265// SmellingSalt
       
if($this->status == self::S_PARALYZED)
       {
        
$bp *= 2;
        
$this->O("%n was cured of paralysis!","|-curestatus|%fslot|par");
        
$this->status 0;
       }
      break;
      case 
311// Weather Ball
       
if($BV->getweather()) $bp *= 2;
      break;
      case 
360// Gyro Ball
       
$bp min(1501+(int)(25*$this->getstat(5)/$user->getstat(5)));
      break;
      case 
486// Electro Ball
       
$ratio = (int)($user->getstat(5)/$this->getstat(5));
       if(
$ratio >= 4$bp 150;
       else if(
$ratio >=3$bp 120;
       else if(
$ratio >= 2$bp 80;
       else if(
$ratio >= 1$bp 60;
       else 
$bp 40;
      break;
      case 
371// Payback
       
if($this->hasmoved$bp *= 2;
      break;
      case 
386// Punishment
       
$bp 60;
       foreach(
$this->statups as $v)
        if(
$v>0$bp += 20*$v;
       
$bp min(200$bp);
      break;
      case 
67: case 447// Low Kick, Grass Knot
       
$w $this->getweight();
       if(
$w >= 200$bp 120;
       else if(
$w >= 100$bp 100;
       else if(
$w >= 50$bp 80;
       else if(
$w >= 25$bp 60;
       else 
$bp 40;
      break;
      case 
484: case 535// Heavy Slam, Heat Crash
       
$w = (int)($user->getweight()/$this->getweight());
       if(
$w >= 5$bp 120;
       else if(
$w >= 4$bp 100;
       else if(
$w >= 3$bp 80;
       else if(
$w >= 2$bp 60;
       else 
$bp 40;
      break;
      case 
506// Hex
       
if($this->status$bp *= 2;
      break;
      case 
167// Truple Kick
       
$bps = array(102030);
       
$bp $bps[$params['curhit']];
      break;
      case 
175: case 179// Flail, Reversal
       
$p = (int)((48 $user->getstat(0,1))/100);
       if(
$p 32$bp 20;
       else if(
$p >= 17$bp 40;
       else if(
$p >= 10$bp 80;
       else if(
$p >= 5$bp 100;
       else if(
$p >= 2$bp 150;
       else 
$bp 200;
      break;
      case 
376// Trump Card
       
$bps = array(40506080200);
       
$BV->debug("PP not implemented"); // TODO
       
$bp $bps[0];
      break;
      case 
217// Present
       
$r $BV->rand(80);
       if(
$r >= 70$bp 120;
       else if(
$r >= 40$bp 80;
       else 
$bp 40;
      break;
      case 
222// Magnitude
       
$r $BV->rand(100);
       if(
$r >= 95$r 6;
       else if(
$r >= 85$r 5;
       else if(
$r >= 65$r 4;
       else if(
$r >= 35$r 3;
       else if(
$r >= 15$r 2;
       else if(
$r >= 5$r 1;
       else 
$r 0;
       
$bp 10+20*$r++;
       
$this->O("Magnitude $r!","|-activate|%fslot|magnitude|$r");
      break;
      case 
205: case 301// Rollout
       
$r true$mul 0;
       foreach(
array_reverse($user->history) as $m)
       {
        if(
$m == $mid)
        {
         if(
$r && $mul<=3$mul++;
         else 
$r=false;
        }
        if(
$mul == 111$mul++; // Defense Curl
       
}
       
$bp <<= $mul;
      break;
      case 
251// Beat Up
       
$i $params['curhit'];
       
$bp 5+(int)($params['beatup'][$i]->base[1]/10);
      break;
      case 
374// Fling
       
if(($user->getitem()) && ($ui=$user->canloseitem(true))
         && (
$r=mysql_fetch_assoc(mysql_query("SELECT bp FROM fling WHERE id='$ui' LIMIT 1"))))
       {
        
$bp $r['bp'];
       }
       else
       {
        
$this->fail();
        
$params['fail'] = true;
        return 
false;
       }
      break;
      case 
450// Bug Bite (before damage to avoid berrycheck in changehp)
       
$a $this->item;
       if(
$a && strpos($ITEMS[$a]['name'],"Berry") && !$this->hadsub)
       {
        
$this->O("%un ate %n's %item!","");
        
$this->useitem("[from] stealeat|[of] %fslot({$user->U})");
        
$i $user->item;
        
$user->item $a$user->berrycheck(true); $user->item $i;
       }
      break;
      
// Fusion Bolt / Fusion Flare
      
case 558$a 559; goto _fusionMove;
      case 
559$a 558_fusionMove:
       if(
$BV->lastmove == $a$bp *= 2;
      break;

      
// TODO TODO TODO
      
case 16// Gust
      
case 239// Twister
      
case 210// Fury Cutter
      
case 255// Spit Up
      
case 497// Echoed Voice
      
case 496// Round
      
case 518// Water Pledge
      
case 519// Fire Pledge
      
case 520// Grass Pledge
       
$BV->debug("Effect not implemented");
      break;
     }

     
$mod 0x1000;

     
// Pursuit, Me First...
     
if($params['bpmul'] != 0x1000chainmod($mod$params['bpmul']);

     if((
$BV->msuser && $atype == 13) || ($BV->wsuser && $atype == 10))
     {
      
chainmod($mod0x548);
     }

     switch(
$user->ability)
     {
      case 
101// Technician
       
if($bp <= 60chainmod($mod0x1800);
      break;
      case 
138// Flare Boost
       
if($user->status == self::S_BURNED && $MOVES[$mid]['cat']==3)
        
chainmod($mod0x1800);
      break;
      case 
148// Analytic
       
if($this->hasmovedchainmod($mod0x14CD);
      break;
      case 
79// Rivalry
       
if($user->gender == $this->genderchainmod($mod0x1400);
       else if((
1-$user->gender) == $this->genderchainmod($mod0xC00);
      break;
      case 
89// Iron Fist
       
if($META[$mid]['flags'] & (1<<8)) chainmod($mod0x1333);
      break;
      case 
120// Reckless
       
if($META[$mid]['recoil']<|| $META[$mid]['effect']==46chainmod($mod0x1333);
      break;
      case 
137// Toxic Boost
       
if($user->status == self::S_POISON && $MOVES[$mid]['cat']==2)
        
chainmod($mod0x1800);
      break;
      case 
159// Sand Force
       
if(in_array($atype, array(569)) && $BV->getweather()==BVideo::W_SANDchainmod($mod0x14CD);
      break;
      case 
125// Sheer Force
       
if($META[$mid]['ailmentchance'] || $META[$mid]['flinchrate'] || ($META[$mid]['statchance'] && $META[$mid]['class']!=7))
       {
        
$params['sheerforce'] = true;
        
chainmod($mod0x14CD);
       }
      break;
     }

     switch(
$this->ability)
     {
      case 
85// Heatproof
       
if($atype == 10 && $this->mbability()) chainmod($mod0x800);
      break;
      case 
87// Dry Skin
       
if($atype == 10chainmod($mod0x1400);
      break;
      case 
154// Justified
       
if($atype == 17$this->statchange(21);
      break;
      case 
155// Rattled
       
if(in_array($atype, array(7,8,17))) $this->statchange(61);
      break;
     }

     
// Gems
     
if($params['gem']) chainmod($mod0x1800);

     
// Plates & Type items
     
$tei = array(222=>7233=>9237=>5238=>6239=>12240=>17241=>2242=>13243=>11244=>3245=>4246=>15247=>8248=>14249=>10250=>16251=>1298=>10299=>11300=>13301=>12302=>15303=>2304=>4305=>5306=>3307=>14308=>7309=>6310=>8311=>16312=>17313=>9);
     if(isset(
$tei[$user->getitem()]) && $atype == $tei[$user->getitem()])
     {
      
chainmod($mod0x1333);
     }

     switch(
$user->getitem())
     {
      case 
266// Muscle Band
       
if($MOVES[$mid]['cat']==2chainmod($mod0x1199);
      break;
      case 
267// Wise Glasses
       
if($MOVES[$mid]['cat']==3chainmod($mod0x1199);
      break;
      case 
136// Lustruous Orb
       
if($user->dex == 484 && in_array($atype, array(1116))) chainmod($mod0x1333);
      break;
      case 
135// Adamant Orb
       
if($user->dex == 483 && in_array($atype, array(916))) chainmod($mod0x1333);
      break;
      case 
112// Griseous Orb
       
if($user->dex == 487 && in_array($atype, array(816))) chainmod($mod0x1333);
      break;
     }

     
// Charge
     
if($user->volatile self::F_CHARGE && $atype==13)
      
chainmod($mod0x2000);

     
// Helping Hand
     
if($user->volatile2 self::F2_HELPINGHANDchainmod($mod0x1800);
     if(
$user->volatile2 self::F2_MEFIRSTchainmod($mod0x1800);

     switch(
$mid)
     {
      case 
362// Brine
       
if($this->getstat(0,1) <= 50chainmod($mod0x2000);
      break;
      case 
474// Venoshock
       
if($this->status == self::S_POISONchainmod($mod0x2000);
      break;
     }

     
$bpmod $mod$basebp $bp;
     
$bp applymod($bp$mod);

     
$mod 0x1000;
     switch(
$user->ability)
     {
      
// Overgrow, Blaze, Torrent, Swarm
      
case 65: case 66: case 67: case 68:
       
$tmp = array(65=>1266=>1067=>1168=>7);
       if(
$tmp[$user->ability]==$atype && (3*$user->hp/$user->bstats[1])<=1)
        
chainmod($mod0x1800);
      break;
      case 
18// Flash Fire
       
if($atype==10 && $user->volatile self::F_FLASHFIREchainmod($mod0x1800);
      break;
      case 
129// Defeatist
       
if($user->getstat(0,1) <= 50chainmod($mod0x800);
      break;
     }

     
// Thick Fat
     
if($this->mbability()==47 && in_array($atype, array(1015))) chainmod($mod0x800);
     
$sid $MOVES[$mid]['cat']==3;

     
damageCalc:

     if(
$mid == 492// Foul Play
      
$at $this->getstat($sid$crit$modtrue);
     else
      
$at $user->getstat($sid$crit$mod, !$mid);

     
$sid++; $invert false;

     if(
$mid)
     {
      if(
$META[$mid]['effect']==283$invert = !$invert;
      if(
$BV->wrcount$invert = !$invert// Wonder Room
      
if($invert$sid = ($sid==2);
     }

     
$df $this->getstat($sid$crit0x1000, !$mid);

     
$dmg = (int)((2*$user->lvl)/5)+2;
     
$dmg = (int)(($dmg*$bp*$at)/$df);
     
$dmg = (int)($dmg/50)+2;

     if(
$mid && $params['tc']>1)
     {
      
$dmg applymod($dmg0xC00);
     }

     if(
$BV->getweather() == BVideo::W_RAIN)
     {
      if(
$atype==10$dmg applymod($dmg0x800);
      if(
$atype==11$dmg applymod($dmg0x1800);
     }
     else if(
$BV->getweather() == BVideo::W_SUN)
     {
      if(
$atype==10$dmg applymod($dmg0x1800);
      if(
$atype==11$dmg applymod($dmg0x800);
     }

     
// Crit
     
if($crit$dmg *= 2;

     
// Random mod
     
$dmgroll = (100-$BV->rand(16))/100;
     
$dmg = (int)($dmg*$dmgroll);
     
$mod 0x1000// Final Mod

     // STAB
     
if($mid != 165// Struggle
     
if($atype == $params['user']->type1 || $atype==$params['user']->type2)
     {
      
$stab = ($user->ability == 91) ? 0x2000 0x1800// Adaptability
      
$dmg applymod($dmg$stab);
     }

     
// Type effectiveness and Burn
     
$dmg = (int)($dmg*$tmul);

     if(
$mid && $user->status == self::S_BURNED
       
&& $MOVES[$mid]['cat']==&& $user->ability != 62$dmg >>= 1;
     if(!
$dmg$dmg++;
     if(!
$mid) goto EndDmg;

     
// Reflect / Light Screen
     
if(!$crit && ($this->ability != 151// Infiltrator
               
&& (($BV->sidee[$this->player%2] & BVideo::S_REFLECT && $MOVES[$mid]['cat']==2)
               || (
$BV->sidee[$this->player%2] & BVideo::S_LIGHTS && $MOVES[$mid]['cat']==3)))
      
chainmod($mod, (($log->leads>=2||$BV->pc>2) ? 0xA8F 0x800));

     
// Target ability
     
switch($this->mbability())
     {
      case 
136// Multiscale
       
if($this->getstat(0,1)==100chainmod($mod0x800);
      break;
      case 
116// Solid Rock
      
case 111// FIlter
       
if($tmul 1chainmod($mod0xC00);
      break;
     }

     
// User ability
     
switch($user->ability)
     {
      case 
97// Sniper
       
if($critchainmod($mod0x1800);
      break;
      case 
110// Tinted Lens
       
if($tmul 1chainmod($mod0x2000);
      break;
     }

     
// Friend Guard
     
foreach(array_merge($params['opponents'], $params['allies']) as $a)
     {
      if((
$a->player%== $this->player%2) && $a->mbability($user) == 132
       
&& ($a->id != $this->id || $a->player != $this->player))
       
chainmod($mod0xC00);
     }

     
// User item
     
switch($user->getitem())
     {
      case 
270// Life Orb
       
chainmod($mod0x14CC);
      break;
      case 
268// Expert Belt
       
if($tmul 1chainmod($mod0x1333);
      break;
      case 
277// Metronome
       
$met 0x1000// Use hhistory but to be accurate should use a success counter (@21D67BC)
       // Interestingly, the charging turn of a move is the one that is used for the history
       
for($i=count($user->history)-1$i>=&& $user->history[$i]==$mid && $user->shistory[$i] && $met 0x1999$i--, $met+=0x333);
       if(
$met 0x1000chainmod($mod$met);
      break;
     }

     
// Type resisting berries
     
if($this->getitem() >= 184 && $this->getitem() <= 200 && !$this->subhp)
     {
      
$tmp = array(184=>10185=>11186=>13187=>12188=>15189=>2190=>4191=>5192=>3193=>14194=>7195=>6196=>8197=>16198=>17199=>9200=>1);
      if(
$atype == $tmp[$this->getitem()])
      {
       
chainmod($mod0x800);
       
$this->O("%n's %item weakens %un's %m power!","");
       
$this->useitem("[weaken]");
      }
     }

     
// Apply final modifier
     
$dmg applymod($dmg$mod);

     
EndDmg:
     
$pc floor((100*$dmg)/($this->bstats[1]));
     
$this->O(($crit?"It's a critical hit! ":'')."%n lost $dmg HP ($pc%).","|debug|Actual damage was $dmg ($pc&#37;)");

     if(
$dmg)
      
$admg $this->changehp(-1*$dmgfalsefalse, (!$mid?"confusion":''));
     else 
$dmg $admg 1;

     if(
$admg && $mid && !$this->hadsub)
      
$this->hurtby[] = array($user->player$user->slot$dmg$MOVES[$mid]['cat']);

     
$params['inflicted'] += $admg;
     if(!
$mid) return;

     
$basebp = isset($basebp) ? $basebp:0;
     
$at = isset($at) ? $at 0;
     
$df = isset($df) ? $df 0;
     
$bpmod = isset($bpmod) ? $bpmod 0x1000;
     
$mod = isset($mod) ? $mod 0x1000;
     
$dmgroll = isset($dmgroll) ? $dmgroll 1;

     
BVideo::debug(sprintf("basebp=$basebp, bpmod=0x%x, stab=0x%x, type=$tmul, random=$dmgroll, at=$at, df=$df, fmod=0x%x.",$bpmod$stab$mod));

     
// Air Balloon
     
if($this->item == 541)
     {
      
$this->O("%n's Air Balloon popped.","");
      
$this->useitem();
     }

     
// Destiny Bond
     
if($this->hp == && $destinybond)
     {
      
$this->O("%n brought down %un with it.","|-activate|%fslot|Destiny Bond");
      
$user->changehp(-10011);
      return;
     }

     
// Moxie
     
if($user->ability == 153 && !$this->hp$user->statchange(21);

     
// Fire move thawing
     
if($atype == 10 && $this->status == self::S_FREEZE)
     {
      
$this->O("%n thawed.","|-curestatus|%fslot|frz");
      
$this->setstatus(0,1);
     }

     
// Anger Point
     
if($crit && $this->ability == 83 && $this->hp)
     {
      
$this->statchange(26);
     }

     switch(
$itm $this->getitem())
     {
      case 
545// Absorb Bulb
       
if($this->hp && $MOVES[$mid]['type'] == 11)
       {
        
$this->O("%n's %item raised its Special Attack!.","");
        
$this->statchange(410"[from] item: %item");
        
$this->useitem("[silent]");
       }
      break;
      case 
546// Cell Battery
       
if($this->hp && $MOVES[$mid]['type'] == 13)
       {
        
$this->O("%n's %item raised its Attack!.","");
        
$this->statchange(210"[from] item: %item");
        
$this->useitem("[silent]");
       }
      break;
     }

     
// Drain effect, Recoil, Rock Head
     
if($admg && ($recoil $META[$mid]['recoil']) && !($user->ability==69 && $recoil<0))
     {
      
// Big Root
      
if($user->getitem() == 296 && $recoil>0$recoil += 16;

      
// Be careful with fp emulated rounding!
      // var_dump($admg/$div,$recoil);
      // 575300734604 float(-47.85)->-48
      // 149738464042 93.5 ->94
      // $hp2 = ceil(($admg*$recoil)/100); Incorrect but seen in emulators
      
$div = (100/$recoil);
      
$hp round($admg/$div0PHP_ROUND_HALF_UP);

      if(!
$hp$hp = ($recoil>: -1);
      if(
$recoil 0)
      {
       if(
$this->ability == 64)
       {
        
$hp *= -1$from "drain";
        
$this->O("%un is hurt by %n's %ab and lost $hp HP.","");
       }
       else
       {
        
$from "drain";
        
$this->O("%n's health is drained! %un regained $hp HP.","");
       }
      }
      else
      {
       
$from "recoil";
       
$this->O("%un is hurt by recoil.","");
      }
      
$user->changehp($hp, -10$this->O("","$from|[of] %fslot",-1));
     }
     if(!
$this->hp) return;
    }
    else 
// Status Move
    
{
     
// Self status
     
if(($ail $META[$mid]['ailment']) && $META[$mid]['target'] == 7)
     {
      if(
$ail 5)
      {
       
$perm true;
       if(
$ail==&& $min && $max && $min==$max$ail self::S_TOXIC;
       if(
$ail == self::S_ASLEEP$params['randduration'] = ($BV->rand(3)+2);
      }
      else
      {
       
$perm false;
       
$ail 1<<($ail-6);
      }
      
$this->setstatus($ail$perm);
     }

     if(
$heal $META[$mid]['healing'])
     {
      
$rounding false;

      
// Moonlight / Synthesis / Morning Sun
      
if($META[$mid]['effect'] == 133)
      {
       switch(
$BV->getweather())
       {
        case 
BVideo::W_NONE$heal 50; break;
        case 
BVideo::W_SUN$heal 66.66; break;
        default: 
$heal 25;
       }
       
$rounding = -1;
      }

      if(
$mid == 256)
      {
       
$heal *= $this->stockpile;
       if(
$heal==75$heal 100;
       
$this->stockpile 0;
       
$this->statchange(3, -1);
       
$this->statchange(5, -1);
      }

      
$this->changehp($heal10"move: %m($mid)"$rounding);
     }

     switch(
$eid $META[$mid]['effect'])
     {
      case 
80// Substitute
       
if($this->subhp$this->fail("Substitute");
       else if(
4*$this->hp <= $this->bstats[1])
        
$this->O("%n is too weak to make a substitute!","|-fail|%fslot|[weak] Substitute");
       else
       {
        
$this->changehp(-2511);
        
$this->subhp $this->bstats[1]>>2;
        
$this->O("%n made a substitute!","|-start|%fslot|Substitute");
       }
      break;

      case 
29// Roar / Whirlwind / ...
       
$this->forceswitch();
      break;

      case 
86// Splash
       
$this->O("But nothing happened!","|-nothing");
      break;

      case 
175// Charge
       
$this->setstatus(self::F_CHARGEfalse);
      break;

      case 
95// Mind Reader
       
$this->mindread 2;
      break;

      case 
114// Foresight
       
$this->O("%n was identified!","|-start|%fslot|foresight");
       
$this->statups[6] = 0;
      break;

      case 
243// Copycat
       
$a $this->planned;
       if(!(
$a[3]=$BV->lastmove) || $a[3] == 383)
       {
        
$this->fail();
        
$params['fail'] = 1;
       }
       else
       {
        
do_action($a, array('mcalled'=>true));
        
$params['noeffects'] = true;
       }
      break;

      case 
10// Mirror Move
       
$a $user->planned;
       if(!(
$a[3]=end($this->history)) || $a[3] == 119)
       {
        
$user->fail();
        
$params['fail'] = 1;
       }
       else
       {
        
do_action($a, array('mcalled'=>true));
        
$params['noeffects'] = true;
       }
      break;

      case 
84// Metronome
       
$a $this->planned;
       
$a[3] = metronome($BV->rand(518));
       
do_action($a, array('mcalled'=>true));
       
$params['noeffects'] = true;
      break;

      case 
181// Assist
       
$bl = array(0,68,102,118,119,144,165,166,168,182,194,197,203,214,243,253,264,266,267,270,271,274,289,343,364,382,383,415,448,476,509,516,525); // Uncallable moves
       
$pool = array();

       foreach(
$partys[$this->player] as $id)
       {
        if(
$id >= $players[$this->player]->partyc) continue;
        
$pk $players[$this->player]->party[$id];
        if(
$pk==$this) continue;
        foreach(
$pk->moves as $mid)
         if(!
in_array($mid,$bl)) $pool[]=$mid;
       }

       if(
count($pool))
       {
        
$a $this->planned;
        
$a[3] = $pool[$BV->rand(count($pool))];
        
do_action($a, array('mcalled'=>true));
       }
       else 
$this->fail();
       
$params['noeffects'] = true;
      break;

      
// Protect, Wideguard, Detect, Quick Guard, Endure
      
case 307$pflag self::F2_QUICKGUARD; goto _protect;
      case 
279$pflag self::F2_WIDEGUARD; goto _protect;
      case 
117$pflag self::F2_ENDURE; goto _protect;
      case 
112$pflag self::F2_PROTECT;
       
_protect:
       
$allmoved true;
       foreach(
array_merge($params['opponents'], $params['allies']) as $a)
       {
        if(!
$a->hasmoved){ $allmoved false; break; }
       }

       if((!
$this->protectcount || !$BV->rand(1<<$this->protectcount)) && !$allmoved)
       {
        
$this->volatile2 |= $pflag;
        
$this->O("","|-singleturn|%fslot|".($pflag==self::F2_PROTECT?"Protect":"%m"));
       }
       else
        
$this->fail();
      break;

      
// Rain Dance, Sunny Day, Sandstorm, Hail
      
case 137: case 138: case 116: case 165:
       
$tmp = array(137=>BVideo::W_RAIN138=>BVideo::W_SUN116=>BVideo::W_SAND165=>BVideo::W_HAIL);
       
$tmp2 = array(137=>285138=>284116=>283165=>282);
       
$BV->setweather($tmp[$eid], ($this->getitem()==$tmp2[$eid]?8:5));
      break;

      case 
26// Haze
       
foreach(array_merge($params['allies'], $params['opponents']) as $pk)
       {
        if(
$pk->hp)
        {
         
$pk->statups = array(0,0,0,0,0,0,0);
        }
       }
       echo 
"All stat changes were eliminated!<br />";
      break;

      case 
226// Tailwind
      
case 66// Reflect
      
case 36// Light Screen
      
case 125// Safeguard
      
case 241// Lucky Chant
      
case 47// Mist
       
$const = array(226 => BVideo::S_TAILWIND66=>BVideo::S_REFLECT36=>BVideo::S_LIGHTS,
         
125=>BVideo::S_SAFEGUARD241=>BVideo::S_LUCKYCHANT47=>BVideo::S_MIST);
       
$ename = array(226 => "tailwind"66=>"reflect"36=>"lightscreen"125=>"safeguard"241=>""47=>"mist");
       
$vn = array(226=>"twcount"66=>"pcount"36=>"lscount"125=>"sgcount"241=>"lccount",47=>"mcount");
       
$lab = array(226 => "speed"66=>"defense"36=>"special defense");

       
$len = ($user->getitem() == 269 5);
       
$dur = array(226=>466=>$len36=>$len125=>5241=>5);

       if(
$BV->sidee[$this->player%2] & $const[$eid])
        
$this->fail();
       else
       {
        
$BV->sidee[$this->player%2] |= $const[$eid];
        
$BV->{$vn[$eid]}[$this->player%2] = $dur[$eid];
        if(
$eid==125$this->O("A protective veil appeared around %n's allies.","");
        else if(
$eid==241$this->O("%n's allies are protected against critical hits!","");
        else if(
$eid == 47$this->O("%n's allies became shrouded in mist!","");
        else 
$this->O("It raised its allies' {$lab[$eid]}!","");
        if(
$e=$ename[$eid]) $this->O("","|-sidestart|%p|$e");
       }
      break;

      case 
267// Stealth Rock
       
$n "Rocks";
       
$BV->sidee[1-$this->player%2] |= BVideo::S_ROCKS;
      goto 
_entryHazMsg;

      case 
250// Toxic Spikes
       
$n "Toxic spikes";
       if(
$BV->sidee[1-$this->player%2] & BVideo::S_TSPIKES1)
        
$BV->sidee[1-$this->player%2] |= BVideo::S_TSPIKES2;
       else 
$BV->sidee[1-$this->player%2] |= BVideo::S_TSPIKES1;
      goto 
_entryHazMsg;

      case 
113// Spikes
       
$n "Spikes";
       if(
$BV->sidee[1-$this->player%2] & BVideo::S_SPIKES2)
        
$BV->sidee[1-$this->player%2] |= BVideo::S_SPIKES3;
       else if(
$BV->sidee[1-$this->player%2] & BVideo::S_SPIKES1)
        
$BV->sidee[1-$this->player%2] |= BVideo::S_SPIKES2;
       else 
$BV->sidee[1-$this->player%2] |= BVideo::S_SPIKES1;

      
_entryHazMsg:
       
$this->O("%m were scattered around %opp's team feet!","|-sidestart|%opp|move: %m");
      break;

      case 
58// Transform
       
$user->transform($this);
      break;

      case 
144// Psych Up
       
$this->O("%un copied %n's stat changes!","|-copyboost|%fslot({$user->U})|%fslot");
       
$user->statups $this->statups;
      break;

      case 
316// Quash
       
if($this->hasmoved$this->fail();
       else
       {
        
$t = &$GLOBALS['turn']; $last count($t)-1;
        
$myid array_search($this->id,$GLOBALS['partys'][$this->player]);
        foreach(
$t as $i=>$al)
         if(
$al[0]==$this->player && $al[1]==$myid) break;

        if(
$i != $last)
        {
         
$tmp array_splice($t$i1); $t[] = $tmp[0]; // Move last
        
}

        
$this->O("%n's move was postponed","|-message|%n's move was postponed!");
       }
      break;

      case 
295// Soak
       
$this->type1 11$this->type2 0;
       
$this->O("%n's type changed to Water.","|-start|%fslot|typechange|Water");
      break;

      case 
252// Aqua Ring
       
$this->volatile |= self::F_AQUARING;
       
$this->O("%n is surrounded by a ring of water.","|-start|%fslot|aquaring");
      break;

      case 
103// Aromatherapy
       
$this->O("","|-cureteam|%fslot");
       foreach(
array_unique(array($this->player, ($this->player+2)%($BV->pc))) as $pl)
       foreach(
$players[$pl]->party as $p)
       {
        if(
$p->hp && $p->status)
         
$p->setstatus(01);
       }
      break;

      case 
143// Belly Drum
       
if(2*$this->hp $this->bstats[1])
       {
        
$this->changehp(-5011);
        
$this->statchange(26);
       }
       else 
$this->fail();
      break;

      case 
169// Memento
       
$this->statchange(2, -2);
       
$this->statchange(4, -2);
      break;

      case 
92// Pain Split
       
$a = ($this->hp+$user->hp)>>1;
       
$this->changehp($a-$this->hp, -11"painsplit");
       
$user->changehp($a-$user->hp, -11"|[silent]");
      break;

      case 
280// Guard Split
       
$stat 3; goto _split;
      case 
281// Power Split
       
$stat 2_split:
       
$a = ($this->bstats[$stat]+$user->bstats[$stat])>>1;
       
$b = ($this->bstats[$stat+2]+$user->bstats[$stat+2])>>1;
       
$this->bstats[$stat] = $user->bstats[$stat] = $a;
       
$this->bstats[$stat+2] = $user->bstats[$stat+2] = $b;
      break;

      case 
244// Power Swap
       
$stat 0; goto _statSwap;
      case 
245// Guard Swap
       
$stat 1;
       
_statSwap:
       
$a $user->statups$b $this->statups;
       
$this->O("%un's and %n's ".($stat?'defensive':'offensive')." stat boosts are swapped.",
        
"|-swapboost|%fslot({$user->U})|%fslot|".($stat?"def, spd":"atk, spa")."|[from] %m");
       list(
$a[$stat],$a[$stat+2],$b[$stat],$b[$stat+2]) = array($b[$stat],$b[$stat+2],$a[$stat],$a[$stat+2]);
       
$user->statups $a$this->statups $b;
      break;

      case 
235// Psycho Shift
       
if($this->status || !$user->status$this->fail();
       else
       {
        
$this->O("%un transfered its status problem to %n.","|-curestatus|%fslot({$user->U})|psychoshift|[of] %fslot");
        
$this->setstatus($user->statustrue);
        
$user->setstatus(self::S_NONEtrue);
       }
      break;

      case 
110// Curse
       
if(in_array(8, array($user->type1$user->type2)))
       {
        
$this->volatile |= self::F_CURSE;
        
$this->O("%un cut its own HP and laid a curse on %n!","|-start|%fslot|curse|[of] %fslot({$user->U})");
        
$user->changehp(-5011);
       }
       else
       {
        
$user->statchange(6, -1);
        
$user->statchange(21);
        
$user->statchange(31);
       }
      break;

      case 
260// Trick Room
       
if($BV->trcount)
       {
        
$BV->trcount 0;
        
$this->O("The dimensions returned to normal.","|-fieldend|trickroom|[of] %fslot");
       }
       else
       {
        
$BV->trcount 5;
        
$this->O("%s twisted the dimensions!","|-fieldstart|trickroom|[of] %fslot");
       }       
      break;

      case 
287// Magic Room
       
if($BV->mrcount)
       {
        
$BV->mrcount 0;
        
$this->O("The use of items returned to normal.","|-fieldend|magicroom|[of] %fslot");
       }
       else
       {
        
$BV->mrcount 5;
        
$this->O("Held items cannot be used!","|-fieldstart|magicroom|[of] %fslot");
       }
      break;

      case 
287// Wonder Room
       
if($BV->wrcount)
       {
        
$BV->wrcount 0;
        
$this->O("Wonder Room wore off.","|-fieldend|wonderroom|[of] %fslot");
       }
       else
       {
        
$BV->wrcount 5;
        
$this->O("It created a bizarre area in which the Defense and Sp. Def stats are swapped!","|-fieldstart|wonderroom|[of] %fslot");
       }
      break;

      case 
216// Gravity
       
if($BV->gravityt)
       {
        
$this->O("Gravity is already in effect.","|-fail|%fslot");
       }
       else
       {
        
$BV->gravityt 5;
        
$this->O("%n intensified the effect of gravity!","|-fieldstart|gravity");
       }
      break;

      case 
173// Rage Powder / Follow Me
       
$this->volatile2 |= self::F2_RAGEPOWDER;
      break;

      case 
177// Helping Hand
       
if($this->player%!= $user->player%2$this->fail();
       else
       {
        
$this->O("%un is ready to help %n!","|-singleturn|%fslot|%m|[of]%fslot({$user->U})");
        
$this->volatile2 |= self::F2_HELPINGHAND;
       }
      break;

      case 
99// Destiny Bond
       
$this->O("%n is trying to take its foe down with it!","|-singlemove|%fslot|%m");
       
$this->volatile |= self::F_DESTINYBOND;
      break;

      case 
184// Magic Coat
       
$this->O("%n shrouded itself with Magic Coat!","|-singleturn|%fslot|%m");
       
$this->volatile2 |= self::F2_MAGICCOAT;
      break;

      case 
239// Power Trick
       
$this->volatile ^= self::F_POWERTRICK;
       
$this->O("%n switched its Attack and Defense!","|-start|%fslot|powertrick");
      break;

      case 
107// Mean Look
       // TODO XXX
       // Do not use damage trapping mechanism for this
       
$this->O("%n cannot escape!","|-message|%n cannot escape!");
      break;

      case 
91// Encore
       // Magic Bounce Encore fails. There is a deeper cause to it
       // in move history, TODO investigate (708633036034)
       
if($params['reflected'] || !$this->setstatus(self::F_ENCORE0))
        
$this->fail();
      break;

      case 
308// Ally Switch
       
$pos array_search($this->id$partys[$this->player]);
       
$p = @$partys[$this->player][1-$pos];
       
$pk = @$players[$this->player]->party[$p];

       if(
$log->leads>&& $pk->onfield)
       {
        
$partys[$this->player][1-$pos] = $this->id;
        
$partys[$this->player][$pos] = $p;
        echo 
"<span class=\"pokemon\">{$this->nick}</span> switched place with <span class=\"pokemon\">{$pk->nick}</span>.<br />";
       }
       else 
$this->fail();
      break;

      case 
119// Swagger
       
$this->statchange(22);
      break;
      case 
167// Flatter
       
$this->statchange(41);
      break;

      case 
185// Recycle
       
if(!$this->item && $this->lastitem)
       {
        
$this->item $this->lastitem;
        
$this->O("%n found one %item!","|-item|%fslot|%item|[from] recycle");
        
$this->checkitem();
       }
       else 
$this->fail();
      break;

      case 
178// Trick
       
$a $user->canloseitem(true);
       
$b $this->canloseitem();
       if((
$a==0&&$b==0) || $a===false || $b===false)
        
$this->fail();
       else
       {
        
$user->O("","|-activate|%fslot|trick|[of] %fslot({$this->U})");
        
$user->item $b$this->item $a;
        if(
$a$this->O("%n obtained one %item($a)!","|-item|%fslot|%item($a)|[from] trick");
        if(
$b$user->O("%n obtained one %item($b)!","|-item|%fslot|%item($b)|[from] trick");
        
$user->checkitem();
        
$this->checkitem();
       }
      break;

      case 
299// Simple Beam
       
$this->setability(86);
      break;

      case 
240// Gastro Acid
       
$this->O("%n's ability is disabled!","|-endability|%fslot|%ab");
       
$this->ability 0;
      break;

      case 
192// Skill Swap
       
$this->O("%un switched ability with %n!","|-activate|%fslot({$user->U})|skillswap");
       
$a $this->ability;
       
$this->setability($user->ability ?: $user->oability);
       
$user->setability($a ?: $this->oability);
      break;

      case 
179// Role Play
       
$user->setability($this->ability?:$this->oability"|[from] roleplay|[of] %fslot($this->U)");
      break;

      case 
300// Entrainment
       
$this->setability($user->oability);
      break;

      case 
227// Acupressure
       
$stat 1+$BV->rand(7);
       if(
$stat==3$stat=5;
       else if(
$stat==4||$stat==5$stat--;
       
$this->statchange(1+$stat2);
      break;

      case 
161// Stockpile
       
if($this->stockpile 3)
       {
        
$i = ++$this->stockpile;
        
$this->O("%n stockpiled $i!","|-start|%fslot|stockpile$i");
        
$this->statchange(31);
        
$this->statchange(51);
       }
       else 
$this->fail();
      break;

      case 
38// Rest
       
$params['randduration'] = 3;
       if(
$this->setstatus(self::S_ASLEEP1))
        
$this->changehp(1001);
      break;

      case 
194// Refreshi
       
$this->setstatus(self::S_NONE,1);
      break;

      case 
215// Roost
       
$this->volatile2 |= self::F2_GROUNDED;
       
$this->O("%n landed on the ground!","|-singleturn|%fslot|%m");
      break;

      case 
94// Conversion 2
       
if($lastm end($this->hhistory))
       {
        
$at $MOVES[$lastm[0]]['type'];
        
$pool = array();

        for(
$i=1$i<=17$i++)
         if(
$GLOBALS['TE'][$at][$i] < 1)
          
$pool[] = $i;

        
$t $pool[$BV->rand(count($pool))];
        echo 
"<span class=\"pokemon\">{$this->nick}</span> became a <img src=\"i/typ/2/$t.png\" alt=\"\" /> type!<br />";
        
$this->O("%n became a {$GLOBALS['HPT'][$t]} type!","|-start|%fslot|typechange|{$GLOBALS['HPT'][$t]}|[from] %m");
        
$this->type1 $t$this->type2 0;
       } else 
$this->fail();
      break;

      case 
319// Reflect Type
       
$user->type1 $this->type1;
       
$user->type2 $this->type2;
       
$this->O("%un's type changed to match %n!","|-start|%fslot({$user->U})|typechange|[of] %fslot");
      break;

      case 
128// Baton Pass
       
$i=0; foreach($players[$this->player]->party as $id=>$pk)
       if(
$id != $this->id && $pk->hp$i++;
       if(!
$i){ $this->fail(); return; }

       
$pool = array(); global $tn;
       for(
$i=0$i $BV->pc$i++)
        
$pool[] = array_shift($log->switchins[$tn]);

       
$log->switchins[$tn] = array_merge($log->switchins[$tn]);
       
$id array_search($this->id$partys[$this->player]);

       foreach(
$pool as $s)
       {
        if(
$s[0]==$this->player && $s[4] == $id)
        {
         
$newp = array("batonpass"=>1);
         
switchin(6$s[0], $s[3], $s[4], $newp);
         return;
        }
       }
      break;
     }
    }
   break;

   case 
self::E_FAIL// Move failed to complete
    // Ugly workaround for granularity difference in triggers
    // Interrupted multi turn moves still trip the confusion trigger
    // TODO Possibly not correct in some corner cases

    // Reset multi turn moves
    
$this->resetmulti();

    
// Reset charging move
    
if(!isset($params['charge']))
     
$this->mcharge 0;

    
$this->O("","|debug|%n was trying to use %m");
    
// 273219967425: Truant/Entrainment/Mimic/Dig battle - very good for testing failure mechanisms
   
break;

   case 
self::E_POSTATTACK:
    
$mid $params['move'];

    if(
$this->mturns)
    {
     if(!--
$this->mturns)
     {
      
$this->params['confturns'] = $BV->rand(4)+2;
      
$this->setstatus(self::F_CONFUSED0);
     }
    }

    switch(
$META[$mid]['effect'])
    {
     case 
330// Relic Song
      
$this->formchange(1-$this->form);
     break;
     case 
221// Healing Wish
     
case 271// Lunar Dance
      
$BV->hwish[$this->player]++;
     case 
169// Memento
      
$this->changehp(-10011);
     return;
     case 
255// Struggle
      
$this->changehp(-2511);
      if(!
$this->hp) return;
     break;
     case 
130// Rapid Spin
      
$tmp $BV->sidee[$this->player%2];
      
$tmp = array($tmp&BVideo::S_ROCKS$tmp&BVideo::S_SPIKES1$tmp&BVideo::S_TSPIKES1);
      
$tmp2 = array("Stealth Rock","Spikes","Toxic Spikes");

      
$BV->sidee[$this->player%2] &= ~63;
      
$this->O("%p's side of the field is cleared of entry hazards.","");
      foreach(
$tmp as $i=>$t)
       if(
$t$this->O("","|-sideend|%p|".$tmp2[$i]);

      if(
$this->trapturns 0)
      {
       
$this->volatile &= ~self::F_TRAPPED$this->trapturns 0;
      }

      if(
$this->volatile self::F_LEECHED)
      {
       
$this->volatile &= ~self::F_LEECHED;
       
$this->O("","|-end|%fslot|leechseed|[from] rapidspin");
      }
     break;
     case 
234// Fling
      
$this->useitem("[from] fling");
     break;
    }

    if(!isset(
$params['sheerforce'])) // Sheer Force
    
{

    
// Flame Burst
    
if($mid == 481 && count($params['opponents'])>1)
    {
     foreach(
$params['opponents'] as $p)
     {
      if(
in_array($p$params['targets']) || !$p->hp) continue;
      
$p->O("The burstling flame hit %n!","");
      
$p->changehp(-6.251);
     }
    }

    
// Life Orb
    
if($this->getitem() == 270 && $MOVES[$mid]['cat']>1)
    {
     
$this->O("%n some HP because of its %item.","");
     
$this->changehp(-10,1,0,"item: Life Orb");
    }

    
// Shell Bell
    
if($this->getitem() == 253)
    {
     if(
$r $params['inflicted'] >> 3)
     {
      
$this->O("%n's %item restored some of its health.","");
      
$this->changehp($r00"%item");
     }
    }

    } 
// Sheer Force

    
if($r $params['inflicted'])
    {
     
$this->hhistory[] = array($mid$r);
    }

    
// U-turn and Volt Switch
    
if(in_array($mid, array(521369)) && $this->hp)
    {
     
$this->effectswitch();
    }
   break;

   case 
self::E_EFFECTS:
    
$mid $params['move'];
    
$user $params['user'];
    if(!
$mid) return;

    
// Sheer Force, Shield Dust
    
if(isset($params['sheerforce']) || ($this->mbability()==19 && $MOVES[$mid]['cat']>1)) goto _foeTriggered;

    if(!
$this->hadsub)
    switch(
$eid $META[$mid]['effect'])
    {
     case 
189// Knock Off
      
if($a=$this->canloseitem())
      {
       
$this->O("%n lost its %item($a)!","");
       
$this->useitem("[from] %m|[of] %fslot({$user->U})");
      }
     break;
     case 
106// Covet / Thief
      
if(($a=$this->canloseitem()) && !$user->item)
      {
       
$this->O("%un stole %n's %item($a)!","|-item|%fslot({$user->U})|%item($a)|[from] %m|[of] %fslot");
       
$this->useitem(); $user->item $a$user->checkitem();
      }
     break;
     case 
234// Fling
      
switch($ui=$user->item)
      {
       case 
236// Light Ball
       
case 245// Poison Barb
       
case 272// Toxic Orb
       
case 273// Flame Orb
        
$tmp = array(236=>self::S_PARALYZED,245=>self::S_POISON,273=>self::S_BURNED272=>self::S_TOXIC);
        
$this->setstatus($tmp[$ui], true);
       break;
       case 
327// Razor Fang
       
case 221// King's Rock
        
$BV->rand(100); // 27-32199-77575 extra flinch call
        
$this->flinch();
       break;
       case 
214// White Herb
       
case 219// Mental Herb
        
$a $this->item$this->item $ui;
        
$this->checkitem(true);
        
$this->item $a;
       break;
      }
      if(
$ui && strpos($ITEMS[$ui]['name'],"Berry"))
      {
       
$a $this->item$this->item $ui;
       
$this->berrycheck(true);
       
$this->item $a;
      }
     break;
     case 
288// Smack Down
      
if((in_array(3, array($this->type1$this->type2)) || $this->ability==26) && !($this->volatile2 self::F2_GROUNDED))
      {
       
$this->O("%n crashed to the ground.","|-start|%fslot|smackdown");
       
$this->grounded 1;
      }
     break;
     case 
266// Captivate
      
if((1-$this->gender) != $user