1. <?php
  2.  
  3. /*
  4.  
  5. License: CC0 (public domain)
  6.   <http://creativecommons.org/publicdomain/zero/1.0/>
  7.  
  8. This license DOES NOT extend to any other files of the Pokemon replay viewer.
  9.  
  10. */
  11.  
  12. include_once 'persist.lib.php';
  13. include_once 'replays.inc.php';
  14. include_once 'data/pokedex.inc.php';
  15. include_once 'data/typechart.inc.php';
  16.  
  17. function parseName($name)
  18. {
  19.     $monthTable = array('january' => '01', 'february' => '02', 'march' => '03', 'april' => '04', 'may' => '05', 'june' => '06', 'july' => '07', 'august' => '08', 'september' => '09', 'october' => '10', 'november' => '11', 'december' => '12');
  20.     if (substr($name, -5) === '.html') $name = substr($name,0,-5);
  21.     if (substr($name, -4) === '.htm') $name = substr($name,0,-4);
  22.     if (preg_match('/^(.*)\-\-([0-9]+) ([A-Z][a-z]+) ([0-9]+) at ([0-9]+)h([0-9]+)$/', $name, $matches))
  23.     {
  24.         $name = trim($matches[1]).'--'.$matches[4].'-'.$monthTable[strtolower($matches[3])].'-'.$matches[2];
  25.     }
  26.     $name = str_replace(' ','-',$name);
  27.    
  28.     $name = preg_replace('/[^A-Za-z0-9-]+/', '', $name);
  29.     return $name;
  30. }
  31.  
  32. function startsRemove(&$str, $substr)
  33. {
  34.     if (substr($str, 0, strlen($substr)) === $substr)
  35.     {
  36.         $str = substr($str, strlen($substr));
  37.         return true;
  38.     }
  39.     return false;
  40. }
  41. function endsRemove(&$str, $substr)
  42. {
  43.     if (substr($str, -strlen($substr)) === $substr)
  44.     {
  45.         $str = substr($str, 0, -strlen($substr));
  46.         return true;
  47.     }
  48.     return false;
  49. }
  50. function startsWith($str, $substr)
  51. {
  52.     return (substr($str, 0, strlen($substr)) === $substr);
  53. }
  54. function endsWith($str, $substr)
  55. {
  56.     return (substr($str, -strlen($substr)) === $substr);
  57. }
  58. function uppercaseFirstLetter($str)
  59. {
  60.     // I am raging at PO replays for this.
  61.     return strtoupper(substr($str,0,1)).substr($str,1);
  62. }
  63. function lowercaseFirstLetter($str)
  64. {
  65.     // I am raging at PO replays for this.
  66.     return strtolower(substr($str,0,1)).substr($str,1);
  67. }
  68.     $pokemontable = array('Bandier' => 'ally-Bandier(Dodrio)', 'Scarfy' => 'ally-Scarfy(Dodrio)');
  69. function namePokemon($pokemon)
  70. {
  71.     global $pokemontable, $allpokemon, $currentpokemon;
  72.     $pokemonConv = $pokemon;
  73.     $pos = strrpos($pokemon, '(');
  74.     if ($pos) $pokemonConv = substr($pokemon, 0, $pos);
  75.     $pokemonConv = str_replace(' ', '', $pokemonConv);
  76.     $currentpokemon[$pokemonConv] = $pokemon;
  77. }
  78. function matchName($pokemon)
  79. {
  80.     global $currentpokemon;
  81.     foreach ($currentpokemon as $mpoke => $cpoke)
  82.     {
  83.         startsRemove($mpoke,'ally-');
  84.         startsRemove($mpoke,'foe-');
  85.         if ($pokemon === $mpoke) return $mpoke;
  86.         else if ($pokemon === uppercaseFirstLetter($mpoke)) return $mpoke;
  87.     }
  88.     return $pokemon;
  89. }
  90. function resolvePokemon($pokemon)
  91. {
  92.     global $convertNotDone, $allpokemon, $allyname, $playernames, $pokemontable, $lastPokemon, $returnNow, $currentpokemon;
  93.     if ($pokemontable[$pokemon])
  94.     {
  95.         $currentpokemon[$pokemontable[$pokemon]] = $pokemontable[$pokemon];
  96.         $lastPokemon = $pokemontable[$pokemon];
  97.         return $pokemontable[$pokemon];
  98.     }
  99.     $pokeid = '';
  100.     //  echo '['.$playernames[0].'|'.$pokemon.']';
  101.     if (startsRemove($pokemon, "The foe's ") || startsRemove($pokemon, "the foe's "))
  102.     {
  103.         $pokeid = $pokemon;
  104.         $pokemon = 'foe-'.$pokemon;
  105.     }
  106.     else if (startsRemove($pokemon, $playernames[0]."'s ") || startsRemove($pokemon, uppercaseFirstLetter($playernames[0])."'s "))
  107.     {
  108.         $pokeid = $pokemon;
  109.         $pokemon = 'ally-'.$pokemon;
  110.     }
  111.     else if (startsRemove($pokemon, $playernames[1]."'s ") || startsRemove($pokemon, uppercaseFirstLetter($playernames[1])."'s "))
  112.     {
  113.         $pokeid = $pokemon;
  114.         $pokemon = 'foe-'.$pokemon;
  115.     }
  116.     else
  117.     {
  118.         $pokeid = $pokemon;
  119.         $pokemon = 'ally-'.matchName($pokemon);
  120.     }
  121.     $pokemon = str_replace(' ', '', $pokemon);
  122.     if ($convertNotDone && $pokeid && $allpokemon[$pokeid])
  123.     {
  124.         if (substr($pokemon,0,4) === 'foe-')
  125.         {
  126.             $allyname = 'foeof-'.$allpokemon[$pokeid];
  127.             $returnNow = true;
  128.             return '';
  129.         }
  130.         $allyname = $allpokemon[$pokeid];
  131.         $returnNow = true;
  132.         return '';
  133.     }
  134.     $lastPokemon = $pokemon;
  135.    
  136.     if ($GLOBALS['BattlePokemon'][getSpecies($pokemon)]['number'] >= 494)
  137.     {
  138.         $GLOBALS['gen'] = 5;
  139.     }
  140.     if ($GLOBALS['BattlePokemon'][getSpecies($pokemon)]['number'] >= 387 && $GLOBALS['gen'] < 4)
  141.     {
  142.         $GLOBALS['gen'] = 4;
  143.     }
  144.     if ($GLOBALS['BattlePokemon'][getSpecies($pokemon)]['number'] >= 252 && $GLOBALS['gen'] < 4)
  145.     {
  146.         $GLOBALS['gen'] = 3;
  147.     }
  148.     if ($GLOBALS['BattlePokemon'][getSpecies($pokemon)]['number'] >= 152 && $GLOBALS['gen'] < 4)
  149.     {
  150.         $GLOBALS['gen'] = 2;
  151.     }
  152.    
  153.     return $pokemon;
  154. }
  155. function getSpecies($pokemon)
  156. {
  157.     global $currentpokemon;
  158.     if ($currentpokemon[$pokemon]) $pokemon = $currentpokemon[$pokemon];
  159.     if (substr($pokemon,0,4) === 'foe-') $pokemon = substr($pokemon,4);
  160.     if (substr($pokemon,0,5) === 'ally-') $pokemon = substr($pokemon,5);
  161.     $pos = strrpos($pokemon, '(');
  162.     if ($pos) $pokemon = substr($pokemon, $pos+1, -1);
  163.     if ($pokemon==='Ho-Oh') $pokemon = "Ho-oh";
  164.     return $pokemon;
  165. }
  166. function resolveMove($move)
  167. {
  168.     return str_replace(' ', '', $move);
  169. }
  170. function resolveUsername($move)
  171. {
  172.     return str_replace(' ', '', $move);
  173. }
  174. function resolveItem($move)
  175. {
  176.     return str_replace(' ', '', $move);
  177. }
  178. function resolveAbility($move)
  179. {
  180.     return str_replace(' ', '', $move);
  181. }
  182. function resolveStat($stat)
  183. {
  184.     $table = array(
  185.         'attack' => 'atk',
  186.         'defense' => 'def',
  187.         'special attack' => 'spa',
  188.         'special defense' => 'spd',
  189.         'sp. att.' => 'spa',
  190.         'sp. def.' => 'spd',
  191.         'speed' => 'spe',
  192.     );
  193.     $stat = strtolower($stat);
  194.     if ($table[$stat]) return $table[$stat];
  195.     return $stat;
  196. }
  197. function isFoe($name)
  198. {
  199.     return resolveUsername($name) !== $GLOBALS['allyname'] && resolveUsername($name) !== uppercaseFirstLetter($GLOBALS['allyname']);
  200. }
  201. function markLastDamage($out)
  202. {
  203.     global $lastPokemon, $lastDamage;
  204.     $lastDamage[$lastPokemon] = count($out)-1;
  205. }
  206. function markLastAttack($out)
  207. {
  208.     global $lastPokemon, $lastAttack;
  209.     $lastAttack[$lastPokemon] = count($out)-1;
  210. }
  211. function attrLastAttack(&$out, $attr)
  212. {
  213.     global $lastPokemon, $lastAttack;
  214.     if ($lastAttack[$lastPokemon])
  215.     {
  216.         $out[$lastAttack[$lastPokemon]] .= ' '.$attr;
  217.     }
  218. }
  219. function makeLastLethal(&$out)
  220. {
  221.     global $lastPokemon, $lastDamage;
  222.     if ($lastDamage[$lastPokemon] && !endsWith($out[$lastDamage[$lastPokemon]], ' (0.0)') && !endsWith($out[$lastDamage[$lastPokemon]], ' (0)'))
  223.     {
  224.         $out[$lastDamage[$lastPokemon]] .= ' (lethal)';
  225.     }
  226. }
  227.  
  228. $logversion = '';
  229. function pokeConvert($text)
  230. {
  231.     global $convertNotDone, $logversion, $returnNow, $allpokemon, $out, $winner, $allyname, $playernames, $moveuser, $lastmove, $convertloopnum;
  232.     $english = false;
  233.     $GLOBALS['gen'] = 1;
  234.     $switchcounter = 0;
  235.     //echo "<div>started</div>";
  236.  
  237.     if (strpos($text, '<!DOCTYPE') === false && strpos($text, '<b><span style=\'color:') !== 0 && !startsWith($text, '<!--Log belonging to '))
  238.     {
  239.         $convertNotDone = false;
  240.         return array('error Replay file must an original Pokemon Online replay file. Copying and pasting replay text into another file will not work.');
  241.     }
  242.  
  243. //echo htmlspecialchars(var_export($text,true));
  244.  
  245. //      if (@$_REQUEST['dev']) echo '1: "'.$text.'"'."\n\n";
  246.  
  247. //$text = preg_replace('/\<!DOCTYPE html\>.*\<head\>/s', '<head>', $text);
  248. {
  249.     $headloc = strpos($text, '<head>');
  250.     if ($headloc) {
  251.         $logversion = substr($text, 0, $headloc);
  252.         if ($versionloc = strpos($logversion, '(version ')) {
  253.             $logversion = substr($logversion, $versionloc+9);
  254.             $logversion = substr($logversion, 0, strpos($logversion, ')'));
  255.             //if (isset($_REQUEST['dev'])) var_dump($logversion);
  256.         }
  257.         $text = substr($text, $headloc);
  258.     }
  259. }
  260.  
  261. $text = preg_replace('/<head\>.*?\<\/head\>/s', '', $text);
  262. $text = preg_replace('/\<\/?(\!DOCTYPE|html|body|p)[^>]*\>/', '', $text);
  263. $text = preg_replace('/\<a[^>]*\>\<span[^>]*\>/', '', $text);
  264. $text = str_replace("</span></a>",'', $text);
  265. $text = str_replace("\n",'', $text);
  266. $text = str_replace("\r",'', $text);
  267. //var_export(htmlspecialchars($text));
  268.  
  269.  
  270. if (strpos($text, '.-->'))
  271. {
  272.     $text = str_replace("-->",'<br />-->', $text);
  273. }
  274.  
  275. $text = explode('<br />', $text);
  276.  
  277.     $allyname = '';
  278.  
  279.     $convertloopnum = 0;
  280.     do
  281.     {
  282.         $convertNotDone = false;
  283.         $returnNow = false;
  284.         $out = pokeConvertInner($text);
  285.         $convertloopnum++;
  286.     } while ($convertNotDone && $convertloopnum < 3);
  287.  
  288.     //echo var_export($allpokemon);
  289.     //echo "<div>$allyname</div>";
  290.  
  291.     if ($convertNotDone)
  292.     {
  293.         return array('error This replay could not be processed.');
  294.     }
  295.     return $out;
  296. }
  297.  
  298. function pokeConvertInner($text)
  299. {
  300.     global $convertNotDone, $returnNow, $currentpokemon, $allpokemon, $out, $winner, $allyname, $playernames, $moveuser, $lastmove, $oldlines, $oldlinesoffset, $convertloopnum;
  301.     $allpokemon = array();
  302.    
  303.     $oldlines = array();
  304.     $oldlinesoffset = 0;
  305.  
  306.     $out = array();
  307.     $winner = false;
  308.     $moveuser = '';
  309.     $lastmove = '';
  310.     $currentpokemon = array();
  311.    
  312.     $firstline = true;
  313.    
  314.     foreach ($text as $i => $line)
  315.     {
  316.         if ($firstline)
  317.         {
  318.             $firstline = false;
  319.         }
  320.         $line = str_replace('&', '&amp;', $line);
  321.        
  322.         $line = preg_replace('/\<span class="[^>]*>/', '', $line, 1, $count);
  323.         if ($count)
  324.         {
  325.             endsRemove($line, '</span>');
  326.         }
  327.        
  328.         $line = str_replace('</span>', '&gt;', $line);
  329.         $line = preg_replace('/\<span[^>]*>/', '&lt;', $line);
  330.         $line = str_replace('</div>', '', $line);
  331.         $line = preg_replace('/\<div[^>]*>/', '', $line);
  332.         $line = str_replace('</a>', '', $line);
  333.         $line = preg_replace('/\<a[^>]*>/', '', $line);
  334.         $line = str_replace('</b>', '&gt;', $line);
  335.         $line = str_replace('<b>', '&lt;', $line);
  336.         $line = trim($line);
  337.         startsRemove($line, '-->');
  338.         if (startsRemove($line, '<!--')) $line = '&lt;!&gt;'.$line;
  339.         if (strpos($line, '<') !== false)
  340.         {
  341.             $convertNotDone = false;
  342.             return array('error This does not appear to be a valid Pokemon Online replay (line '.($i+1).': '.($line).').');
  343.         }
  344.         $line = str_replace('&gt;', '>', $line);
  345.         $line = str_replace('&lt;', '<', $line);
  346.         $line = str_replace('>>', '>', $line);
  347.         $line = str_replace('<<', '<', $line);
  348.         $line = str_replace('&amp;', '&', $line);
  349.         $line = trim($line);
  350.         $newline = $line;
  351.         $oldlines[] = array(count($out), $newline);
  352.         if ($line === '')
  353.         {
  354.             $out[] = '';
  355.         }
  356.         else if (startsRemove($line, '<!>'))
  357.         {
  358.             $outcount = count($out);
  359.             //$lastline = '';
  360.             if ($outcount > 1) $lastline =& $out[$outcount-1];
  361.             $statuses = array(
  362.                 'fine' => 'none',
  363.                 'koed' => 'fnt'
  364.             );
  365.             if (startsRemove($line, 'Log belonging to '))
  366.             {
  367.                 //$allyname = resolveUsername($line);
  368.             }
  369.             else if (preg_match('/^([^<>]+) sent out ([^<>]+)!( \([^<>]+\))?$/', $line, $matches))
  370.             {
  371.                 $pokemon = (isFoe($matches[1])?'foe-':'ally-').$matches[2].$matches[3];
  372.                 namePokemon($pokemon);
  373.                 $pokemon = str_replace(' ','',$pokemon);
  374.                 if ($lastmove === 'Roar' || $lastmove === 'Whirlwind' || $lastmove === 'DragonTail' || $lastmove === 'CircleThrow')
  375.                 {
  376.                     $out[] = 'drag-out-anim switched-'.$pokemon;
  377.                 }
  378.                 else
  379.                 {
  380.                     $out[] = 'replace switched-'.$pokemon;
  381.                 }
  382.             }
  383.             else if (preg_match('/^([^<>]+)\'s life: ([0-9]+)%.$/', $line, $matches))
  384.             {
  385.                 if (startsWith($lastline, 'switch-in ') || startsWith($lastline, 'replace '))
  386.                 {
  387.                     $lastline .= ' ('.$matches[2].')';
  388.                 }
  389.             }
  390.             else if (preg_match('/^([^<>]+)\'s life: ([0-9]+)\/([0-9]+) HP.$/', $line, $matches))
  391.             {
  392.                 if (startsWith($lastline, 'switch-in ') || startsWith($lastline, 'replace '))
  393.                 {
  394.                     $lastline .= ' ('.number_format(100*intval($matches[2])/intval($matches[3]), 1, '.', '').')';
  395.                 }
  396.             }
  397.             else if (preg_match('/^([^<>]+)\'s status: ([a-z]+).$/', $line, $matches))
  398.             {
  399.                 $status = $statuses[$matches[2]];
  400.                 if ($status)
  401.                 {
  402.                     if (startsWith($lastline, 'switch-in ') || startsWith($lastline, 'replace '))
  403.                     {
  404.                         if (endsWith($lastline,')'))
  405.                         {
  406.                             $lastline = substr($lastline,0,-1).'|'.$statuses[$matches[2]].')';
  407.                         }
  408.                         else $lastline = $lastline.' ('.$statuses[$matches[2]].')';
  409.                     }
  410.                 }
  411.             }
  412.             else if (preg_match('/^([^<>]+)\'s new HP is ([0-9]+)\/([0-9]+).$/', $line, $matches) ||
  413.                      preg_match('/^([^<>]+)\'s new HP is ([0-9]+)%.$/', $line, $matches))
  414.             {
  415.                 if (!$matches[3]) $newhp = $matches[2];
  416.                 else $newhp = number_format(100*intval($matches[2])/intval($matches[3]), 1, '.', '');
  417.                 if ($GLOBALS['logversion'] !== '2.0' || $matches[3])
  418.                 {
  419.                     if (startsWith($lastline,'  r-recoil ') || startsWith($lastline,'  r-life-orb-recoil '))
  420.                     {
  421.                         $lastline .= ' ('.$newhp.')';
  422.                     }
  423.                     else if (startsWith($lastline,'stealth-rock-damage '))
  424.                     {
  425.                         $lastline .= ' ('.$newhp.')';
  426.                     }
  427.                     else if (startsWith($lastline,'  r-damage '))
  428.                     {
  429.                         $lastline .= ' ('.$newhp.')';
  430.                     }
  431.                     else if (startsWith($lastline,'residual ') && (strpos($lastline, ' leech-seed ') || strpos($lastline, ' item-heal ') || strpos($lastline, ' wish ')))
  432.                     {
  433.                         $lastline .= ' ('.$newhp.')';
  434.                     }
  435.                 }
  436.             }
  437.         }
  438.         else if (startsRemove($line, '<Tier: >'))
  439.         {
  440.             $out[] = 'tier '.$line;
  441.         }
  442.         else if (startsRemove($line, '<Variation: >'))
  443.         {
  444.             $out[] = 'variation '.$line;
  445.         }
  446.         else if (startsRemove($line, '<Rule: >'))
  447.         {
  448.             $out[] = 'rule '.$line;
  449.         }
  450.         else if (startsRemove($line, '<Start of turn '))
  451.         {
  452.             endsRemove($line, '>');
  453.             endsRemove($line, '!');
  454.             $out[] = 'turn '.$line;
  455.             if (substr($line, 0, -1) === '1' && $switchcounter < 100) $switchcounter += 100;
  456.             else if ($switchcounter < 100) $switchcounter += 200;
  457.             // damage doesn't actually happen here, but any undetected messages that do damage...
  458.             markLastDamage($out);
  459.         }
  460.         else if (endsRemove($line, ' fainted!>'))
  461.         {
  462.             $out[] = 'faint '.resolvePokemon(substr($line, 1));
  463.             makeLastLethal($out);
  464.         }
  465.         else if (endsRemove($line, ' is exerting its Pressure!'))
  466.         {
  467.             $out[] = '  r-pressure '.resolvePokemon($line);
  468.         }
  469.         else if (endsRemove($line, ' has Mold Breaker!'))
  470.         {
  471.             $out[] = '  r-mold-breaker '.resolvePokemon($line);
  472.         }
  473.         else if (endsRemove($line, ' is hit with recoil!'))
  474.         {
  475.             $out[] = '  r-recoil '.resolvePokemon($line).' ??';
  476.             markLastDamage($out);
  477.         }
  478.         else if ($line === "<It's not very effective...>")
  479.         {
  480.             $out[] = '  r-resisted';
  481.         }
  482.         else if ($line === "But it failed!")
  483.         {
  484.             $out[] = '  r-failed '.$moveuser;
  485.         }
  486.         else if ($line === "But there was no target...")
  487.         {
  488.             $out[] = '  r-no-target '.$moveuser;
  489.             attrLastAttack($out, 'no-target');
  490.         }
  491.         else if ($line === "It had no effect!")
  492.         {
  493.             $out[] = '  r-immune '.$movetarget;
  494.         }
  495.         else if ($line === "<But nothing happened!>")
  496.         {
  497.             $out[] = '  r-nothing-happened';
  498.         }
  499.         else if ($line === "<It's super effective!>")
  500.         {
  501.             $out[] = '  r-super-effective';
  502.         }
  503.         else if ($line === "<A critical hit!>")
  504.         {
  505.             $out[] = '  r-crit';
  506.         }
  507.         else if ($line === "<It hurt itself in its confusion!>")
  508.         {
  509.             $out[] = '  r-hurt-confusion';
  510.         }
  511.         else if ($line === "<It's a one hit KO!>")
  512.         {
  513.             $out[] = '  r-ohko';
  514.         }
  515.         else if ($line === "<The sunlight is strong!>")
  516.         {
  517.             $out[] = 'weather-upkeep sun';
  518.         }
  519.         else if ($line === "<Rain continues to fall!>")
  520.         {
  521.             $out[] = 'weather-upkeep rain';
  522.         }
  523.         else if ($line === "<The sunlight turned harsh!>")
  524.         {
  525.             $out[] = 'weather sun';
  526.         }
  527.         else if ($line === "<It started to rain!>")
  528.         {
  529.             $out[] = 'weather rain';
  530.         }
  531.         else if ($line === "<A hailstorm brewed!>")
  532.         {
  533.             $out[] = 'weather hail';
  534.         }
  535.         else if ($line === "<Hail continues to fall!>")
  536.         {
  537.             $out[] = 'weather hail';
  538.         }
  539.         else if ($line === "<A sandstorm brewed!>")
  540.         {
  541.             $out[] = 'weather sandstorm';
  542.         }
  543.         else if ($line === "<The sandstorm rages!>")
  544.         {
  545.             $out[] = 'weather-upkeep sandstorm';
  546.         }
  547.         else if ($line === "<The sunlight faded!>")
  548.         {
  549.             $out[] = 'weather none';
  550.         }
  551.         else if ($line === "<The rain stopped!>")
  552.         {
  553.             $out[] = 'weather none';
  554.         }
  555.         else if ($line === "<The sandstorm subsided!>")
  556.         {
  557.             $out[] = 'weather none';
  558.         }
  559.         else if ($line === "<The hail subsided!>")
  560.         {
  561.             $out[] = 'weather none';
  562.         }
  563.         else if ($line === '<All stat changes were eliminated!>')
  564.         {
  565.             $out[] = '  r-haze';
  566.         }
  567.         else if ($line === '<The battlers shared their pain!>')
  568.         {
  569.             $out[] = '  r-pain-split';
  570.         }
  571.         else if (endsRemove($line, '\'s Wonder Guard evades the attack!'))
  572.         {
  573.             $out[] = '  r-ability-evade '.resolvePokemon($line).' WonderGuard';
  574.         }
  575.         else if (endsRemove($line, ' avoided the attack!'))
  576.         {
  577.             attrLastAttack($out, 'miss');
  578.             $out[] = '  r-avoid '.resolvePokemon($line).'';
  579.         }
  580.         else if (endsRemove($line, ' regained health!>'))
  581.         {
  582.             $out[] = '  r-heal '.resolvePokemon(substr($line, 1)).' ??';
  583.         }
  584.         else if (endsRemove($line, ' restored some HP!'))
  585.         {
  586.             $out[] = '  r-heal '.resolvePokemon($line).' ??';
  587.         }
  588.         else if (endsRemove($line, ' was poisoned!>'))
  589.         {
  590.             if ($lastmove === 'Toxic')
  591.             {
  592.                 $out[] = '  r-status '.resolvePokemon(substr($line, 1)).' toxic';
  593.             }
  594.             else
  595.             {
  596.                 $out[] = '  r-status '.resolvePokemon(substr($line, 1)).' psn';
  597.             }
  598.         }
  599.         else if (endsRemove($line, ' was badly poisoned!>'))
  600.         {
  601.             $out[] = '  r-status '.resolvePokemon(substr($line, 1)).' toxic';
  602.         }
  603.         else if (endsRemove($line, ' is already poisoned.>'))
  604.         {
  605.             $out[] = '  r-status '.resolvePokemon(substr($line, 1)).' psn already';
  606.         }
  607.         else if (endsRemove($line, ' is already burnt.>'))
  608.         {
  609.             $out[] = '  r-status '.resolvePokemon(substr($line, 1)).' brn already';
  610.         }
  611.         else if (endsRemove($line, ' is already paralyzed.>'))
  612.         {
  613.             $out[] = '  r-status '.resolvePokemon(substr($line, 1)).' par already';
  614.         }
  615.         else if (endsRemove($line, ' calmed down!>'))
  616.         {
  617.             $out[] = '  r-calm '.resolvePokemon(substr($line, 1));
  618.         }
  619.         else if (endsRemove($line, ' is confused!>'))
  620.         {
  621.             $out[] = 'pre-move '.resolvePokemon(substr($line, 1)).' confused';
  622.         }
  623.         else if (endsRemove($line, ' is fast asleep!>'))
  624.         {
  625.             $out[] = 'pre-move '.resolvePokemon(substr($line, 1)).' slp';
  626.         }
  627.         else if (endsRemove($line, ' is being sent back!>'))
  628.         {
  629.             $out[] = 'pre-move '.resolvePokemon(substr($line, 1)).' switch-out';
  630.         }
  631.         else if (endsRemove($line, ' woke up!>'))
  632.         {
  633.             $out[] = '  r-cure-status '.resolvePokemon(substr($line, 1)).' slp';
  634.         }
  635.         else if (endsRemove($line, '\'s status cleared!'))
  636.         {
  637.             $out[] = '  r-cure '.resolvePokemon($line);
  638.         }
  639.         else if (endsRemove($line, '\'s status cleared!>'))
  640.         {
  641.             $out[] = '  r-cure '.resolvePokemon(substr($line, 1));
  642.         }
  643.         else if (endsRemove($line, ' landed on the ground!>'))
  644.         {
  645.             $out[] = '  r-turnstatus '.resolvePokemon(substr($line, 1)).' landed';
  646.         }
  647.         else if (endsRemove($line, ' protected itself!>'))
  648.         {
  649.             $out[] = '  r-turnstatus '.resolvePokemon(substr($line, 1)).' protect';
  650.         }
  651.         else if (endsRemove($line, ' shrouded itself with Magic Coat!>'))
  652.         {
  653.             $out[] = '  r-turnstatus '.resolvePokemon(substr($line, 1)).' magic-coat';
  654.         }
  655.         else if (endsRemove($line, ' braced itself!>'))
  656.         {
  657.             $out[] = '  r-turnstatus '.resolvePokemon(substr($line, 1)).' endure';
  658.         }
  659.         else if (endsRemove($line, ' is tightening its focus!>'))
  660.         {
  661.             $out[] = '  r-turnstatus '.resolvePokemon(substr($line, 1)).' focusing';
  662.         }
  663.         else if (endsRemove($line, ' is hurt by poison!>'))
  664.         {
  665.             $out[] = 'residual '.resolvePokemon(substr($line, 1)).' poison ??';
  666.             markLastDamage($out);
  667.         }
  668.         else if (endsRemove($line, ' is hurt by its burn!>'))
  669.         {
  670.             $out[] = 'residual '.resolvePokemon(substr($line, 1)).' burn ??';
  671.             markLastDamage($out);
  672.         }
  673.         else if (endsRemove($line, ' was burned!>'))
  674.         {
  675.             $out[] = '  r-status '.resolvePokemon(substr($line, 1)).' brn';
  676.         }
  677.         else if (endsRemove($line, ' is paralyzed! It may be unable to move!>'))
  678.         {
  679.             $out[] = '  r-status '.resolvePokemon(substr($line, 1)).' par';
  680.         }
  681.         else if (endsRemove($line, ' is paralyzed! It can\'t move!>'))
  682.         {
  683.             $out[] = 'cant-move '.resolvePokemon(substr($line, 1)).' fully-paralyzed';
  684.         }
  685.         else if (endsRemove($line, ' can\'t attack while in the air!>'))
  686.         {
  687.             $out[] = 'cant-move '.resolvePokemon(substr($line, 1)).' in-air';
  688.         }
  689.         else if (endsRemove($line, ' became confused!>'))
  690.         {
  691.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' confused';
  692.         }
  693.         else if (endsRemove($line, ' snapped out its confusion!>'))
  694.         {
  695.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' confused end';
  696.         }
  697.         else if (endsRemove($line, " was prevented from healing!>"))
  698.         {
  699.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' healblock';
  700.         }
  701.         else if (endsRemove($line, " must recharge!>"))
  702.         {
  703.             $out[] = 'cant-move '.resolvePokemon(substr($line, 1)).' must-recharge';
  704.         }
  705.         else if (endsRemove($line, " vanished instantly!>"))
  706.         {
  707.             $out[] = 'prepare-move '.resolvePokemon(substr($line, 1)).' ShadowForce';
  708.         }
  709.         else if (endsRemove($line, " sprang up!>"))
  710.         {
  711.             $out[] = 'prepare-move '.resolvePokemon(substr($line, 1)).' Bounce';
  712.         }
  713.         else if (endsRemove($line, " burrowed its way under the ground!>"))
  714.         {
  715.             $out[] = 'prepare-move '.resolvePokemon(substr($line, 1)).' Dig';
  716.         }
  717.         else if (endsRemove($line, " hid underwater!>"))
  718.         {
  719.             $out[] = 'prepare-move '.resolvePokemon(substr($line, 1)).' Dive';
  720.         }
  721.         else if (endsRemove($line, " flew high up!>"))
  722.         {
  723.             $out[] = 'prepare-move '.resolvePokemon(substr($line, 1)).' Fly';
  724.         }
  725.         else if (endsRemove($line, " absorbed light!>"))
  726.         {
  727.             $out[] = 'prepare-move '.resolvePokemon(substr($line, 1)).' SolarBeam';
  728.         }
  729.         else if (endsRemove($line, " became cloaked in a harsh light!>"))
  730.         {
  731.             $out[] = 'prepare-move '.resolvePokemon(substr($line, 1)).' SkyAttack';
  732.         }
  733.         else if (endsRemove($line, "'s heal block wore off!>"))
  734.         {
  735.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' healblock end';
  736.         }
  737.         else if (endsRemove($line, ' fell asleep!>'))
  738.         {
  739.             $out[] = '  r-status '.resolvePokemon(substr($line, 1)).' slp';
  740.         }
  741.         else if (endsRemove($line, ' woke up!'))
  742.         {
  743.             $out[] = '  r-cure-status '.resolvePokemon($line).' slp';
  744.         }
  745.         else if (endsRemove($line, ' was frozen solid!>'))
  746.         {
  747.             $out[] = '  r-status '.resolvePokemon(substr($line, 1)).' frz';
  748.         }
  749.         else if (endsRemove($line, ' thawed out!>'))
  750.         {
  751.             $out[] = '  r-cure-status '.resolvePokemon(substr($line, 1)).' frz';
  752.         }
  753.         else if (endsRemove($line, ' is frozen solid!>'))
  754.         {
  755.             $out[] = 'cant-move '.resolvePokemon(substr($line, 1)).' frozen';
  756.         }
  757.         else if (endsRemove($line, ' cut its own HP and maximized its Attack!>'))
  758.         {
  759.             $out[] = '  r-belly-drum '.resolvePokemon(substr($line, 1)).'';
  760.         }
  761.         else if (endsRemove($line, ' flinched!'))
  762.         {
  763.             $out[] = 'flinch '.resolvePokemon($line);
  764.         }
  765.         else if (endsRemove($line, ' is hurt by its Life Orb!'))
  766.         {
  767.             $out[] = '  r-life-orb-recoil '.resolvePokemon($line).' ??';
  768.             markLastDamage($out);
  769.         }
  770.         else if (endsRemove($line, ' is floating on a balloon!>'))
  771.         {
  772.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' balloon';
  773.         }
  774.         else if (endsRemove($line, ' is floating on a balloon!'))
  775.         {
  776.             $out[] = '  r-volatile '.resolvePokemon($line).' balloon';
  777.         }
  778.         else if (endsRemove($line, "'s Air Balloon popped!>") || endsRemove($line, "'s Balloon popped!>"))
  779.         {
  780.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' balloon end';
  781.         }
  782.         else if (endsRemove($line, "'s Air Balloon popped!") || endsRemove($line, "'s Balloon popped!"))
  783.         {
  784.             $out[] = '  r-volatile '.resolvePokemon($line).' balloon end';
  785.         }
  786.         else if (endsRemove($line, "'s Rain Dish heals it!>"))
  787.         {
  788.             $out[] = 'residual '.resolvePokemon(substr($line, 1)).' ability-heal RainDish';
  789.         }
  790.         else if (endsRemove($line, "'s Ice Body heals it!>"))
  791.         {
  792.             $out[] = 'residual '.resolvePokemon(substr($line, 1)).' ability-heal IceBody';
  793.         }
  794.         else if (endsRemove($line, " was seeded!>"))
  795.         {
  796.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' seed';
  797.         }
  798.         else if (endsRemove($line, "'s Drought intensified the sun's rays!>"))
  799.         {
  800.             $out[] = '  r-weather '.resolvePokemon(substr($line, 1)).' sun';
  801.         }
  802.         else if (endsRemove($line, "'s Sand Stream whipped up a sandstorm!>"))
  803.         {
  804.             $out[] = '  r-weather '.resolvePokemon(substr($line, 1)).' sandstorm';
  805.         }
  806.         else if (endsRemove($line, " is buffeted by the sandstorm!>"))
  807.         {
  808.             $out[] = 'residual '.resolvePokemon(substr($line, 1)).' sandstorm ??';
  809.             markLastDamage($out);
  810.         }
  811.         else if (endsRemove($line, "'s Snow Warning whipped up a hailstorm!>"))
  812.         {
  813.             $out[] = '  r-weather '.resolvePokemon(substr($line, 1)).' hail';
  814.         }
  815.         else if (endsRemove($line, " is buffeted by the hail!>"))
  816.         {
  817.             $out[] = 'residual '.resolvePokemon(substr($line, 1)).' hail ??';
  818.             markLastDamage($out);
  819.         }
  820.         else if (endsRemove($line, "'s Drizzle made it rain!>"))
  821.         {
  822.             $out[] = '  r-weather '.resolvePokemon(substr($line, 1)).' rain';
  823.         }
  824.         else if (endsRemove($line, " twisted the dimensions!>"))
  825.         {
  826.             $out[] = '  r-pseudo-weather '.resolvePokemon(substr($line, 1)).' TrickRoom';
  827.         }
  828.         else if ($line === '<The twisted dimensions returned to normal!>')
  829.         {
  830.             $out[] = 'pseudo-weather-end TrickRoom';
  831.         }
  832.         else if (endsRemove($line, " swapped the Sp. Def. and the Defense of all the pokemon!>"))
  833.         {
  834.             $out[] = '  r-pseudo-weather '.resolvePokemon(substr($line, 1)).' WonderRoom';
  835.         }
  836.         else if ($line === '<The Sp. Def and Defense of the pokemon went back to normal!>')
  837.         {
  838.             $out[] = 'pseudo-weather-end WonderRoom';
  839.         }
  840.         else if (endsRemove($line, " cancelled the items' effects!>"))
  841.         {
  842.             $out[] = '  r-pseudo-weather '.resolvePokemon(substr($line, 1)).' MagicRoom';
  843.         }
  844.         else if ($line === '<The items are now working again!>')
  845.         {
  846.             $out[] = 'pseudo-weather-end MagicRoom';
  847.         }
  848.         else if (endsRemove($line, " is already preparing its next move!"))
  849.         {
  850.             $out[] = '  r-custap '.resolvePokemon($line);
  851.         }
  852.         else if (startsRemove($line, "<It doesn't affect "))
  853.         {
  854.             $out[] = '  r-doesnt-affect '.resolvePokemon(substr($line, 0, -4));
  855.         }
  856.         else if (endsRemove($line, "mon hearing the song will faint in three turns!>"))
  857.         {
  858.             $out[] = '  r-perish-song '.$moveuser;
  859.         }
  860.         else if (endsRemove($line, "'s health is sapped by leech seed.>"))
  861.         {
  862.             $out[] = 'residual '.resolvePokemon(substr($line, 1)).' leech-seed ?? ??';
  863.             markLastDamage($out);
  864.         }
  865.         else if (endsRemove($line, " has Teravolt!"))
  866.         {
  867.             $out[] = '  r-ability-notify '.resolvePokemon($line).' Teravolt';
  868.         }
  869.         else if (endsRemove($line, " has Cloud Nine!"))
  870.         {
  871.             $out[] = '  r-ability-notify '.resolvePokemon($line).' CloudNine';
  872.         }
  873.         else if (endsRemove($line, " has Air Lock!"))
  874.         {
  875.             $out[] = '  r-ability-notify '.resolvePokemon($line).' AirLock';
  876.         }
  877.         else if (endsRemove($line, " has Turboblaze!") || endsRemove($line, " has Turbo Blaze!"))
  878.         {
  879.             $out[] = '  r-ability-notify '.resolvePokemon($line).' Turboblaze';
  880.         }
  881.         else if (endsRemove($line, " has Turboblaze!") || endsRemove($line, " has TeraVoltage!"))
  882.         {
  883.             $out[] = '  r-ability-notify '.resolvePokemon($line).' Teravolt';
  884.         }
  885.         else if (endsRemove($line, "'s Speed Boost increases its speed!"))
  886.         {
  887.             $out[] = 'residual '.resolvePokemon($line).' ability-activate SpeedBoost';
  888.         }
  889.         else if (endsRemove($line, "'s Poison Point activates!>"))
  890.         {
  891.             $out[] = 'residual '.resolvePokemon(substr($line,1)).' ability-activate PoisonPoint';
  892.         }
  893.         else if (endsRemove($line, "'s Download activates!"))
  894.         {
  895.             $out[] = 'residual '.resolvePokemon($line).' ability-activate Download';
  896.         }
  897.         else if (endsRemove($line, "'s Cursed Body activates!"))
  898.         {
  899.             $out[] = 'residual '.resolvePokemon($line).' ability-activate CursedBody';
  900.         }
  901.         else if (endsRemove($line, "'s Flame Body activates!>"))
  902.         {
  903.             $out[] = 'residual '.resolvePokemon(substr($line,1)).' ability-activate FlameBody';
  904.         }
  905.         else if (endsRemove($line, "'s stat changes were eliminated!>"))
  906.         {
  907.             $out[] = '  r-poke-haze '.resolvePokemon(substr($line,1)).'';
  908.         }
  909.         else if (endsRemove($line, "'s Quick Claw activated!"))
  910.         {
  911.             $out[] = 'residual '.resolvePokemon($line).' item-activate QuickClaw';
  912.             $lastmove = 'Toxic';
  913.         }
  914.         else if (endsRemove($line, "'s Toxic Orb activated!"))
  915.         {
  916.             $out[] = 'residual '.resolvePokemon($line).' item-activate ToxicOrb';
  917.             $lastmove = 'Toxic';
  918.         }
  919.         else if (endsRemove($line, "'s Flame Orb activated!"))
  920.         {
  921.             $out[] = 'residual '.resolvePokemon($line).' item-activate FlameOrb';
  922.         }
  923.         else if (endsRemove($line, ' was dragged out!>'))
  924.         {
  925.             $prevline = count($out)-1;
  926.             if ($out[$prevline] === 'faint '.resolvePokemon(substr($line, 1)))
  927.             {
  928.                 $out[$prevline] = 'drag-out '.resolvePokemon(substr($line, 1));
  929.                 $out[] = 'faint '.resolvePokemon(substr($line, 1));
  930.             }
  931.             else
  932.             {
  933.                 $out[] = 'drag-out '.resolvePokemon(substr($line, 1));
  934.             }
  935.         }
  936.         else if (endsRemove($line, ' made a substitute!>'))
  937.         {
  938.             $out[] = '  r-sub '.resolvePokemon(substr($line, 1));
  939.         }
  940.         else if (endsRemove($line, ' already has a substitute.>'))
  941.         {
  942.             $out[] = '  r-sub '.resolvePokemon(substr($line, 1)).' already';
  943.         }
  944.         else if (endsRemove($line, ' is already confused.>'))
  945.         {
  946.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' confused already';
  947.         }
  948.         else if (endsRemove($line, ' hung on using its Focus Sash!') || endsRemove($line, ' hung on using its focus sash!'))
  949.         {
  950.             $out[] = '  r-sash '.resolvePokemon($line);
  951.         }
  952.         else if (endsRemove($line, ' held on thanks to Sturdy!'))
  953.         {
  954.             $out[] = '  r-sturdy '.resolvePokemon($line);
  955.             $GLOBALS['gen'] = 5;
  956.         }
  957.         else if (endsRemove($line, ' regains health with its Regenerator!') || endsRemove($line, ' regains health with its Regeneration!'))
  958.         {
  959.             // ignore
  960.         }
  961.         else if (endsRemove($line, ' is watching the battle.>'))
  962.         {
  963.             $out[] = 'spectator '.substr($line, 1);
  964.         }
  965.         else if (endsRemove($line, ' stopped watching the battle.>'))
  966.         {
  967.             $out[] = 'spectator-end '.substr($line, 1);
  968.         }
  969.         else if (endsRemove($line, ' had its energy drained!'))
  970.         {
  971.             $out[] = '  r-drain '.resolvePokemon($line).' ?? ??';
  972.         }
  973.         else if (endsRemove($line, ' went to sleep and became healthy!>'))
  974.         {
  975.             $out[] = '  r-rested '.resolvePokemon(substr($line,1)).'';
  976.         }
  977.         else if (startsRemove($line, '<Pointed stones dug into '))
  978.         {
  979.             $pokemon = resolvePokemon(substr($line, 0, -2));
  980.             $damage = 12.5 * getDamageTaken('Rock', $GLOBALS['BattlePokemon'][getSpecies($pokemon)]);
  981.             //echo '['.$pokemon.'|'.getSpecies($pokemon).']';
  982.             $out[] = 'stealth-rock-damage '.$pokemon.' '.$damage;
  983.             markLastDamage($out);
  984.         }
  985.         else if (endsRemove($line, "'s wish came true!>"))
  986.         {
  987.             $out[] = 'residual ?? wish '.resolveUsername(substr($line, 1)).' ??';
  988.         }
  989.         else if ($line === "<The healing wish came true!>")
  990.         {
  991.             $out[] = 'residual ?? healing-wish ?? ??';
  992.         }
  993.         else if ($line === "<A soothing aroma wafted through the area!>")
  994.         {
  995.             $out[] = '  r-cure-all '.$moveuser.' Aromatherapy';
  996.         }
  997.         else if ($line === "<A bell chimed!>")
  998.         {
  999.             $out[] = '  r-cure-all '.$moveuser.' HealBell';
  1000.         }
  1001.         else if (endsRemove($line, " has bad dreams!>"))
  1002.         {
  1003.             $out[] = 'residual '.resolvePokemon(substr($line, 1)).' bad-dreams ??';
  1004.             markLastDamage($out);
  1005.         }
  1006.         else if (endsRemove($line, " took the Doom Desire attack!>"))
  1007.         {
  1008.             $out[] = 'residual '.resolvePokemon(substr($line, 1)).' move DoomDesire';
  1009.         }
  1010.         else if (endsRemove($line, " chose Doom Desire as its destiny!>"))
  1011.         {
  1012.             $out[] = '  r-doom-desire '.resolvePokemon(substr($line, 1));
  1013.         }
  1014.         else if (endsRemove($line, ' is hurt by spikes!>'))
  1015.         {
  1016.             $out[] = 'spikes-damage '.resolvePokemon(substr($line, 1)).' ??';
  1017.             markLastDamage($out);
  1018.         }
  1019.         else if (endsRemove($line, ' blew away Leech Seed!>'))
  1020.         {
  1021.             $out[] = '  r-blow-away '.resolvePokemon(substr($line, 1)).' LeechSeed';
  1022.         }
  1023.         else if (endsRemove($line, ' blew away Stealth Rock!>'))
  1024.         {
  1025.             $out[] = '  r-blow-away '.resolvePokemon(substr($line, 1)).' StealthRock';
  1026.         }
  1027.         else if (endsRemove($line, ' blew away Spikes!>'))
  1028.         {
  1029.             $out[] = '  r-blow-away '.resolvePokemon(substr($line, 1)).' Spikes';
  1030.         }
  1031.         else if (endsRemove($line, ' blew away Toxic Spikes!>'))
  1032.         {
  1033.             $out[] = '  r-blow-away '.resolvePokemon(substr($line, 1)).' ToxicSpikes';
  1034.         }
  1035.         else if (endsRemove($line, ' fell for the taunt!>'))
  1036.         {
  1037.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' taunt';
  1038.         }
  1039.         else if (endsRemove($line, '\'s Flash Fire raised the power of its Fire-type moves!>'))
  1040.         {
  1041.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' flash-fire';
  1042.         }
  1043.         else if (endsRemove($line, ' is now tormented!>'))
  1044.         {
  1045.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' torment';
  1046.         }
  1047.         else if (endsRemove($line, ' received an encore!>'))
  1048.         {
  1049.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' encore';
  1050.         }
  1051.         else if (endsRemove($line, "'s taunt ended!>"))
  1052.         {
  1053.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' taunt end';
  1054.         }
  1055.         else if (endsRemove($line, "'s Encore ended!>"))
  1056.         {
  1057.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' encore end';
  1058.         }
  1059.         else if (endsRemove($line, "'s substitute faded!>"))
  1060.         {
  1061.             $out[] = '  r-sub-fade '.resolvePokemon(substr($line, 1));
  1062.         }
  1063.         else if (endsRemove($line, "'s substitute took the damage!>"))
  1064.         {
  1065.             $out[] = '  r-sub-damage '.resolvePokemon(substr($line, 1));
  1066.         }
  1067.         else if (endsRemove($line, " planted its roots!>"))
  1068.         {
  1069.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' ingrain';
  1070.         }
  1071.         else if (endsRemove($line, " surrounded itself with a veil of water!>"))
  1072.         {
  1073.             $out[] = '  r-volatile '.resolvePokemon(substr($line, 1)).' aqua-ring';
  1074.         }
  1075.         else if (endsRemove($line, " absorbed nutrients with its roots!>"))
  1076.         {
  1077.             $out[] = 'residual '.resolvePokemon(substr($line, 1)).' heal ingrain';
  1078.         }
  1079.         else if (startsRemove($line, "<Aquaring restored "))
  1080.         {
  1081.             endsRemove($line, "'s HP.>");
  1082.             $out[] = 'residual '.resolvePokemon($line).' heal aqua-ring';
  1083.         }
  1084.         else if (endsRemove($line, " is trying to take its foe with it!>"))
  1085.         {
  1086.             $out[] = '  r-destiny-bond '.resolvePokemon(substr($line, 1));
  1087.         }
  1088.         else if (preg_match('/^\<([^<>]+) can\'t use ([^<>]+) after the taunt!\>$/', $line, $matches))
  1089.         {
  1090.             $out[] = 'cant-move '.resolvePokemon($matches[1]).' taunt '.resolveMove($matches[2]);
  1091.         }
  1092.         else if (preg_match('/^([^<>]+) used \<([^<>]+)\>!$/', $line, $matches))
  1093.         {
  1094.             $moveuser = resolvePokemon($matches[1]);
  1095.             $movetarget = 'foeof-'.resolvePokemon($matches[1]);
  1096.             $lastmove = resolveMove($matches[2]);
  1097.             $out[] = 'move '.$moveuser.' '.resolveMove($matches[2]).' ??';
  1098.             markLastAttack($out);
  1099.            
  1100.             if ($matches[2] === 'Explosion' || $matches[2] === 'Selfdestruct' || $matches[2] === 'Lunar Dance' || $matches[2] === 'Healing Wish' || $matches[2] === 'Memento' || $matches[2] === 'Final Gambit')
  1101.             {
  1102.                 markLastDamage($out);
  1103.             }
  1104.         }
  1105.         else if (preg_match('/^([^<>]+) sent out ([^<>]+)!( \([^<>]+\))?$/', $line, $matches))
  1106.         {
  1107.             if ($allpokemon[$matches[2]] && $allpokemon[$matches[2]] != resolveUsername($matches[1]))
  1108.             {
  1109.                 $allpokemon[$matches[2]] = false;
  1110.             }
  1111.             else if ($allpokemon[$matches[2]] !== false)
  1112.             {
  1113.                 $allpokemon[$matches[2]] = resolveUsername($matches[1]);
  1114.             }
  1115.             $pokemon = (isFoe($matches[1])?'foe-':'ally-').$matches[2].$matches[3];
  1116.             namePokemon($pokemon);
  1117.             $pokemon = str_replace(' ','',$pokemon);
  1118.             $out[] = 'switch-in switched-'.$pokemon;
  1119.             $lastmove = 'switch';
  1120.            
  1121.             if ($switchcounter < 99) $switchcounter++;
  1122.         }
  1123.         else if (preg_match('/^\<Pointed stones float in the air around ([^<>]+)\'s team!\>?$/', $line, $matches))
  1124.         {
  1125.             $side = (isFoe($matches[1])?'foe':'ally');
  1126.             $out[] = '  r-side-condition '.$side.' StealthRock';
  1127.         }
  1128.         else if (preg_match('/^\<Spikes were scattered all around the feet of ([^<>]+)\'s team!\>?$/', $line, $matches))
  1129.         {
  1130.             $side = (isFoe($matches[1])?'foe':'ally');
  1131.             $out[] = '  r-side-condition '.$side.' Spikes';
  1132.         }
  1133.         else if (preg_match('/^\<Poison spikes were scattered all around the feet of ([^<>]+)\'s team!\>?$/', $line, $matches))
  1134.         {
  1135.             $side = (isFoe($matches[1])?'foe':'ally');
  1136.             $out[] = '  r-side-condition '.$side.' ToxicSpikes';
  1137.         }
  1138.         else if (preg_match('/^\<A tailwind started blowing behind ([^<>]+)\'s team!\>?$/', $line, $matches))
  1139.         {
  1140.             $side = (isFoe($matches[1])?'foe':'ally');
  1141.             $out[] = '  r-side-condition '.$side.' Tailwind';
  1142.         }
  1143.         else if (preg_match('/^\<([^<>]+)\'s team tailwind petered out!\>?$/', $line, $matches))
  1144.         {
  1145.             $side = (isFoe($matches[1])?'foe':'ally');
  1146.             $out[] = 'side-condition '.$side.' Tailwind end';
  1147.         }
  1148.         else if (preg_match('/^\<Reflect raised ([^<>]+)\'s team defense!\>?$/', $line, $matches))
  1149.         {
  1150.             $side = (isFoe($matches[1])?'foe':'ally');
  1151.             $out[] = '  r-side-condition '.$side.' Reflect';
  1152.         }
  1153.         else if (preg_match('/^\<([^<>]+)\'s reflect wore off!\>?$/', $line, $matches))
  1154.         {
  1155.             $side = (isFoe($matches[1])?'foe':'ally');
  1156.             $out[] = '  r-side-condition '.$side.' Reflect end';
  1157.         }
  1158.         else if (preg_match('/^\<([^<>]+)\'s team became cloaked in a mystical veil!\>?$/', $line, $matches))
  1159.         {
  1160.             $side = (isFoe($matches[1])?'foe':'ally');
  1161.             $out[] = '  r-side-condition '.$side.' Safeguard';
  1162.         }
  1163.         else if (preg_match('/^\<([^<>]+)\'s team is no longer protected by Safeguard!\>?$/', $line, $matches))
  1164.         {
  1165.             $side = (isFoe($matches[1])?'foe':'ally');
  1166.             $out[] = '  r-side-condition '.$side.' Safeguard end';
  1167.         }
  1168.         else if (preg_match('/^\<Light Screen raised ([^<>]+)\'s team special defense!\>?$/', $line, $matches))
  1169.         {
  1170.             $side = (isFoe($matches[1])?'foe':'ally');
  1171.             $out[] = '  r-side-condition '.$side.' LightScreen';
  1172.         }
  1173.         else if (preg_match('/^\<([^<>]+)\'s light screen wore off!\>?$/', $line, $matches))
  1174.         {
  1175.             $side = (isFoe($matches[1])?'foe':'ally');
  1176.             $out[] = '  r-side-condition '.$side.' LightScreen end';
  1177.         }
  1178.         else if (preg_match('/^\<([^<>]+) shattered ([^<>]+)\'s team protections!\>?$/', $line, $matches))
  1179.         {
  1180.             $side = (isFoe($matches[2])?'foe':'ally');
  1181.             $out[] = '  r-shatter '.resolvePokemon($matches[1]).' '.$side;
  1182.         }
  1183.         else if (preg_match('/^([^<>]+)\'s Synchronize changes the status of ([^<>]+)!$/', $line, $matches))
  1184.         {
  1185.             $out[] = 'residual '.resolvePokemon($matches[1]).' ability-activate Synchronize '.resolvePokemon($matches[2]).'';
  1186.         }
  1187.         else if (preg_match('/^([^<>]+) called ([^<>]+) back!$/', $line, $matches))
  1188.         {
  1189.             $pokemon = (isFoe($matches[1])?'foe-':'ally-').$matches[2];
  1190.             $pokemon = str_replace(' ','',$pokemon);
  1191.             $out[] = 'switch-out '.$pokemon;
  1192.         }
  1193.         else if (preg_match('/^\<?([^<>]+) transformed into ([^<>]+)!\>?$/', $line, $matches))
  1194.         {
  1195.             $out[] = '  r-transform '.resolvePokemon($matches[1]).' '.resolveUsername($matches[2]).'';
  1196.         }
  1197.         else if (preg_match('/^\<([^<>]+) made ([^<>]+) feel drowsy!\>$/', $line, $matches))
  1198.         {
  1199.             $out[] = '  r-volatile '.resolvePokemon($matches[2]).' drowsy start '.resolvePokemon($matches[1]).'';
  1200.         }
  1201.         else if (preg_match('/^([^<>]+) is hurt by ([^<>]+)\'s ([A-Za-z .\']+)!$/', $line, $matches))
  1202.         {
  1203.             $out[] = '  r-foe-item-damage '.resolvePokemon($matches[1]).' '.resolvePokemon($matches[2]).' '.resolveItem($matches[3]).' ??';
  1204.             resolvePokemon($matches[1]); // is the one taking the damage
  1205.             markLastDamage($out);
  1206.         }
  1207.         else if (preg_match('/^\<([^<>]+) was hurt by ([A-Za-z .\']+)!\>$/', $line, $matches))
  1208.         {
  1209.             $out[] = 'residual '.resolvePokemon($matches[1]).' move-damage '.resolveItem($matches[2]).' ??';
  1210.             markLastDamage($out);
  1211.         }
  1212.         else if (preg_match('/^([^<>]+) is hurt by its ([A-Za-z .\']+)!$/', $line, $matches))
  1213.         {
  1214.             $out[] = 'residual '.resolvePokemon($matches[1]).' item-damage '.resolveItem($matches[2]).' ??';
  1215.             markLastDamage($out);
  1216.         }
  1217.         else if (preg_match('/^([^<>]+) was hurt by Black Sludge!$/', $line, $matches))
  1218.         {
  1219.             $out[] = 'residual '.resolvePokemon($matches[1]).' item-damage BlackSludge ??';
  1220.             markLastDamage($out);
  1221.         }
  1222.         else if (preg_match('/^([^<>]+) restored its stats using ([A-Za-z .\']+)!$/', $line, $matches))
  1223.         {
  1224.             $out[] = 'residual '.resolvePokemon($matches[1]).' item-restore '.resolveItem($matches[2]);
  1225.         }
  1226.         else if (preg_match('/^([^<>]+) restored a little HP using its ([A-Za-z .\']+)!$/', $line, $matches))
  1227.         {
  1228.             $out[] = 'residual '.resolvePokemon($matches[1]).' item-heal '.resolveItem($matches[2]);
  1229.         }
  1230.         else if (preg_match('/^\<([^<>]+) restored HP using its ([A-Za-z .\']+)!\>$/', $line, $matches))
  1231.         {
  1232.             $out[] = 'residual '.resolvePokemon($matches[1]).' ability-heal '.resolveAbility($matches[2]);
  1233.         }
  1234.         else if (preg_match('/^([^<>]+) used its Mental Herb to come back to (his|her|its) senses!$/', $line, $matches))
  1235.         {
  1236.             $out[] = 'residual '.resolvePokemon($matches[1]).' item-customcure MentalHerb';
  1237.         }
  1238.         else if (preg_match('/^\<([^<>]+)\'s Hydration heals its status!\>$/', $line, $matches))
  1239.         {
  1240.             $out[] = 'residual '.resolvePokemon($matches[1]).' ability-cure Hydration';
  1241.         }
  1242.         else if (preg_match('/^\<([^<>]+)\'s Insomnia cures it!\>$/', $line, $matches))
  1243.         {
  1244.             $out[] = 'residual '.resolvePokemon($matches[1]).' ability-cure Insomnia';
  1245.         }
  1246.         else if (preg_match('/^\<([^<>]+)\'s Shed Skin heals its status!\>$/', $line, $matches))
  1247.         {
  1248.             $out[] = 'residual '.resolvePokemon($matches[1]).' ability-cure ShedSkin';
  1249.         }
  1250.         else if (preg_match('/^The attack of ([^<>]+) missed!$/', $line, $matches))
  1251.         {
  1252.             $out[] = '  r-miss '.resolvePokemon($matches[1]);
  1253.             attrLastAttack($out, 'miss');
  1254.         }
  1255.         else if (preg_match('/^([^<>]+)\'s ([a-zA-Z .]+) drastically fell!$/', $line, $matches))
  1256.         {
  1257.             $out[] = '  r-unboost '.resolvePokemon($matches[1]).' '.resolveStat($matches[2]).' 3';
  1258.         }
  1259.         else if (preg_match('/^([^<>]+)\'s ([a-zA-Z .]+) sharply fell!$/', $line, $matches))
  1260.         {
  1261.             $out[] = '  r-unboost '.resolvePokemon($matches[1]).' '.resolveStat($matches[2]).' 2';
  1262.         }
  1263.         else if (preg_match('/^([^<>]+)\'s ([a-zA-Z .]+) fell!$/', $line, $matches))
  1264.         {
  1265.             $out[] = '  r-unboost '.resolvePokemon($matches[1]).' '.resolveStat($matches[2]).' 1';
  1266.         }
  1267.         else if (preg_match('/^([^<>]+) lost ([0-9]+)% of its health!$/', $line, $matches))
  1268.         {
  1269.             $out[] = '  r-damage '.resolvePokemon($matches[1]).' '.$matches[2];
  1270.             markLastDamage($out);
  1271.         }
  1272.         else if (preg_match('/^([^<>]+) lost ([0-9]+) HP! \(([0-9]+)% of its health\)$/', $line, $matches))
  1273.         {
  1274.             $out[] = '  r-damage '.resolvePokemon($matches[1]).' '.$matches[3];
  1275.             markLastDamage($out);
  1276.         }
  1277.         else if (preg_match('/^([^<>]+) traced ([^<>]+)\'s ([A-Za-z ]+)!$/', $line, $matches))
  1278.         {
  1279.             $out[] = '  r-trace '.resolvePokemon($matches[1]).' '.resolvePokemon($matches[2]).' '.resolveAbility($matches[3]);
  1280.         }
  1281.         else if (preg_match('/^\<([^<>]+) knocked off ([^<>]+)\'s ([A-Za-z ]+)!\>$/', $line, $matches))
  1282.         {
  1283.             $out[] = '  r-knock-off '.resolvePokemon($matches[1]).' '.resolvePokemon($matches[2]).' '.resolveAbility($matches[3]);
  1284.         }
  1285.         else if (preg_match('/^\<([^<>]+) knocked ([^<>]+) on the ground!\>$/', $line, $matches))
  1286.         {
  1287.             $out[] = '  r-volatile '.resolvePokemon($matches[2]).' grounded start '.resolvePokemon($matches[1]);
  1288.         }
  1289.         else if (preg_match('/^\<([^<>]+)\'s substitute blocked ([^<>]+)!\>$/', $line, $matches))
  1290.         {
  1291.             $out[] = '  r-sub-block '.resolvePokemon($matches[1]).' '.resolveMove($matches[2]);
  1292.         }
  1293.         else if (preg_match('/^\<(.+?): \>([^<>]+)$/', $line, $matches))
  1294.         {
  1295.             $out[] = 'chat '.resolveUsername($matches[1]).' '.$matches[2];
  1296.         }
  1297.         else if (preg_match('/^\<(.+?): \>\<([^<>]+)\>$/', $line, $matches))
  1298.         {
  1299.             $out[] = 'chat '.resolveUsername($matches[1]).' '.$matches[2];
  1300.         }
  1301.         else if (preg_match('/^\<(.+?)\>: ([^<>]+)$/', $line, $matches))
  1302.         {
  1303.             $out[] = 'chat '.resolveUsername($matches[1]).' '.$matches[2];
  1304.         }
  1305.         else if (preg_match('/^\<([^<>]+) flung its ([^<>]+)!\>$/', $line, $matches))
  1306.         {
  1307.             $out[] = '  r-fling '.resolvePokemon($matches[1]).' '.resolveItem($matches[2]);
  1308.         }
  1309.         else if (preg_match('/^([^<>]+) ate its ([^<>]+)!$/', $line, $matches))
  1310.         {
  1311.             $out[] = '  r-eat '.resolvePokemon($matches[1]).' '.resolveItem($matches[2]);
  1312.         }
  1313.         else if (preg_match('/^([^<>]+)\'s ([a-zA-Z .\']+) weakened ([^<>]+)\'s power!$/', $line, $matches))
  1314.         {
  1315.             $out[] = '  r-weaken '.resolvePokemon($matches[1]).' '.resolveMove($matches[3]).' '.resolveItem($matches[2]);
  1316.         }
  1317.         else if (preg_match('/^\<([^<>]+) stole and ate ([^<>]+)\'s ([^<>]+)!\>$/', $line, $matches))
  1318.         {
  1319.             $out[] = '  r-steal-eat '.resolvePokemon($matches[1]).' '.resolvePokemon($matches[2]).' '.resolveItem($matches[3]);
  1320.         }
  1321.         else if (preg_match('/^\<([^<>]+)\'s Storm Drain raised its special attack!\>$/', $line, $matches))
  1322.         {
  1323.             $out[] = '  r-ability-boost '.resolvePokemon($matches[1]).' spa 1 StormDrain';
  1324.         }
  1325.         else if (preg_match('/^\<?([^<>]+)\'s Competitive Spirit sharply raised its Attack!\>?$/', $line, $matches))
  1326.         {
  1327.             $out[] = '  r-ability-boost '.resolvePokemon($matches[1]).' atk 2 CompetitiveSpirit';
  1328.         }
  1329.         else if (preg_match('/^\<?([^<>]+)\'s Lightningrod raised its (Special Attack|special attack)!\>?$/', $line, $matches))
  1330.         {
  1331.             $out[] = '  r-ability-boost '.resolvePokemon($matches[1]).' spa 1 Lightningrod';
  1332.         }
  1333.         else if (preg_match('/^\<?([^<>]+)\'s (Justified|Justice Heart) raised its attack!\>?$/', $line, $matches))
  1334.         {
  1335.             $out[] = '  r-ability-boost '.resolvePokemon($matches[1]).' atk 1 Justified';
  1336.         }
  1337.         else if (preg_match('/^\<?([^<>]+)\'s (Herbivore|Sap Sipper) raised its attack!\>?$/', $line, $matches))
  1338.         {
  1339.             $out[] = '  r-ability-boost '.resolvePokemon($matches[1]).' atk 1 SapSipper';
  1340.         }
  1341.         else if (preg_match('/^\<?([^<>]+)\'s Motor Drive raise(d|s) its speed!\>?$/', $line, $matches))
  1342.         {
  1343.             $out[] = '  r-ability-boost '.resolvePokemon($matches[1]).' spe 1 MotorDrive';
  1344.         }
  1345.         else if (preg_match('/^\<?([^<>]+)\'s (Steadfast|SteadFast) increases its speed!\>?$/', $line, $matches))
  1346.         {
  1347.             $out[] = '  r-ability-boost '.resolvePokemon($matches[1]).' spe 1 Steadfast';
  1348.         }
  1349.         else if (preg_match('/^([^<>]+)\'s Absorb Bulb raised its Sp. Att.!$/', $line, $matches))
  1350.         {
  1351.             $out[] = '  r-ability-boost '.resolvePokemon($matches[1]).' spa 1 AbsorbBulb';
  1352.         }
  1353.         else if (preg_match('/^([^<>]+)\'s (Moody|Inconsistent) sharply raises its ([a-zA-Z .\']+)!$/', $line, $matches))
  1354.         {
  1355.             $out[] = '  r-ability-boost '.resolvePokemon($matches[1]).' '.resolveStat($matches[3]).' 2 Moody';
  1356.         }
  1357.         else if (preg_match('/^([^<>]+)\'s (Moody|Inconsistent) lowers its ([a-zA-Z .\']+)!$/', $line, $matches))
  1358.         {
  1359.             $out[] = '  r-ability-unboost '.resolvePokemon($matches[1]).' '.resolveStat($matches[3]).' 1 Moody';
  1360.         }
  1361.         else if (preg_match('/^([^<>]+)\'s ([a-zA-Z .\']+) raised ([^<>]+)\'s power!$/', $line, $matches))
  1362.         {
  1363.             $out[] = '  r-gem '.resolvePokemon($matches[1]).' '.resolveItem($matches[2]).' '.resolveMove($matches[3]).'';
  1364.         }
  1365.         else if (preg_match('/^The ([a-zA-Z .\']+) raised ([^<>]+)\'s ([a-zA-Z .\']+)!$/', $line, $matches))
  1366.         {
  1367.             $out[] = '  r-item-boost '.resolvePokemon($matches[2]).' '.resolveStat($matches[3]).' 1 '.resolveItem($matches[1]).'';
  1368.         }
  1369.         else if (preg_match('/^\<([^<>]+) switched items with ([^<>]+)!\>$/', $line, $matches))
  1370.         {
  1371.             $out[] = '  r-trick '.resolvePokemon($matches[1]).' '.resolvePokemon($matches[2]);
  1372.         }
  1373.         else if (preg_match('/^<([^<>]+) obtained one ([a-zA-Z .\']+)!>$/', $line, $matches))
  1374.         {
  1375.             $out[] = '  r-trick-get '.resolvePokemon($matches[1]).' '.resolveItem($matches[2]).'';
  1376.         }
  1377.         else if (preg_match('/^([^<>]+)\'s ([a-zA-Z .]+) drastically rose!$/', $line, $matches))
  1378.         {
  1379.             $out[] = '  r-boost '.resolvePokemon($matches[1]).' '.resolveStat($matches[2]).' 3';
  1380.         }
  1381.         else if (preg_match('/^([^<>]+)\'s ([a-zA-Z .]+) sharply rose!$/', $line, $matches))
  1382.         {
  1383.             if ($lastmove === 'TailGlow')
  1384.             {
  1385.                 $out[] = '  r-boost '.resolvePokemon($matches[1]).' '.resolveStat($matches[2]).' 3';
  1386.             }
  1387.             else
  1388.             {
  1389.                 $out[] = '  r-boost '.resolvePokemon($matches[1]).' '.resolveStat($matches[2]).' 2';
  1390.             }
  1391.         }
  1392.         else if (preg_match('/^([^<>]+)\'s ([a-zA-Z .]+) rose!$/', $line, $matches))
  1393.         {
  1394.             $out[] = '  r-boost '.resolvePokemon($matches[1]).' '.resolveStat($matches[2]).' 1';
  1395.         }
  1396.         else if (preg_match('/^\<([^<>]+) stockpiled ([1-3])!\>$/', $line, $matches))
  1397.         {
  1398.             $out[] = '  r-volatile '.resolvePokemon($matches[1]).' stockpile'.$matches[2];
  1399.         }
  1400.         else if (preg_match('/^\<([^<>]+)\'s perish count fell to ([0-3]).\>$/', $line, $matches))
  1401.         {
  1402.             $out[] = '  r-volatile '.resolvePokemon($matches[1]).' perish'.$matches[2];
  1403.             if ($matches[2] === '0') markLastDamage($out);
  1404.         }
  1405.         else if (preg_match('/^([^<>]+) intimidates ([^<>]+)!$/', $line, $matches))
  1406.         {
  1407.             $out[] = '  r-intimidate '.resolvePokemon($matches[1]).' '.resolvePokemon($matches[2]);
  1408.         }
  1409.         else if (preg_match('/^\<([^<>]+) moved its status onto ([^<>]+)!\>$/', $line, $matches))
  1410.         {
  1411.             $out[] = '  r-psycho-shift '.resolvePokemon($matches[1]).' '.resolvePokemon($matches[2]);
  1412.         }
  1413.         else if (preg_match('/^\<([^<>]+) took ([^<>]+) down with it!\>$/', $line, $matches))
  1414.         {
  1415.             $out[] = '  r-also-ko '.resolvePokemon($matches[1]).' '.resolvePokemon($matches[2]);
  1416.             markLastDamage($out);
  1417.         }
  1418.         else if (preg_match('/^\<The poison spikes disappeared around ([^<>]+)\'s feet!\>$/', $line, $matches))
  1419.         {
  1420.             $out[] = '  r-absorb-spikes '.resolvePokemon($matches[1]).' ToxicSpikes';
  1421.         }
  1422.         else if (preg_match('/^\<([^<>]+) lost some HP because of Solar Power!\>$/', $line, $matches))
  1423.         {
  1424.             $out[] = 'residual '.resolvePokemon($matches[1]).' ability-damage SolarPower ??';
  1425.             markLastDamage($out);
  1426.         }
  1427.         else if (preg_match('/^\<([^<>]+)\'s ([A-Z][a-z]+) Absorb absorbs the attack!\>$/', $line, $matches))
  1428.         {
  1429.             $out[] = '  r-ability-heal '.resolvePokemon($matches[1]).' '.$matches[2].'Absorb ??';
  1430.         }
  1431.         else if (preg_match('/^\<([^<>]+)\'s ([A-Z][a-z]+) Absorb made the attack useless!\>$/', $line, $matches))
  1432.         {
  1433.             $out[] = '  r-ability-heal '.resolvePokemon($matches[1]).' '.$matches[2].'Absorb ??';
  1434.         }
  1435.         else if (preg_match('/^([^<>]+)\'s Iron Barbs hurts ([^<>]+)$/', $line, $matches))
  1436.         {
  1437.             $out[] = '  r-ability-damage '.resolvePokemon($matches[1]).' '.resolvePokemon($matches[2]).' IronBarbs ??';
  1438.             resolvePokemon($matches[2]);
  1439.             markLastDamage($out);
  1440.         }
  1441.         else if (preg_match('/^([^<>]+)\'s Rough Skin hurts ([^<>]+)$/', $line, $matches))
  1442.         {
  1443.             $out[] = '  r-ability-damage '.resolvePokemon($matches[1]).' '.resolvePokemon($matches[2]).' RoughSkin ??';
  1444.             resolvePokemon($matches[2]);
  1445.             markLastDamage($out);
  1446.         }
  1447.         else if (preg_match('/^([^<>]+)\'s Aftermath damages ([^<>]+)!$/', $line, $matches))
  1448.         {
  1449.             $out[] = '  r-ability-damage '.resolvePokemon($matches[1]).' '.resolvePokemon($matches[2]).' Aftermath ??';
  1450.             resolvePokemon($matches[2]);
  1451.             markLastDamage($out);
  1452.         }
  1453.         else if (preg_match('/^\<([^<>]+)\'s ([^<>]+) was bounced back by Magic Mirror!\>$/', $line, $matches))
  1454.         {
  1455.             $out[] = '  r-bounce-back '.resolvePokemon($matches[1]).' MagicMirror '.resolveMove($matches[2]);
  1456.         }
  1457.         else if (preg_match('/^\<([^<>]+)\'s ([^<>]+) was bounced back by Magic Coat!\>$/', $line, $matches))
  1458.         {
  1459.             $out[] = '  r-bounce-back '.resolvePokemon($matches[1]).' MagicCoat '.resolveMove($matches[2]);
  1460.         }
  1461.         else if (preg_match('/^\<Battle between ([^<>]+) and ([^<>]+) is underway!\>$/', $line, $matches))
  1462.         {
  1463.             $out[] = 'player '.$matches[1];
  1464.             $out[] = 'foe-player '.$matches[2];
  1465.             $out[] = 'start';
  1466.             $allyname = resolveUsername($matches[1]);
  1467.             $playernames = array($matches[1],$matches[2]);
  1468.             $english = 'warn';
  1469.         }
  1470.         else if (preg_match('/^\<Battle between ([^<>]+) and ([^<>]+) started!\>$/', $line, $matches))
  1471.         {
  1472.             if ($allyname === '' && $convertloopnum === 0)
  1473.             {
  1474.                 $convertNotDone = true;
  1475.             }
  1476.             else if ($allyname === resolveUsername($matches[1]) || (substr($allyname, 0,6) === 'foeof-' && substr($allyname, 6) === resolveUsername($matches[2])))
  1477.             {
  1478.                 $out[] = 'player '.$matches[1];
  1479.                 $out[] = 'foe-player '.$matches[2];
  1480.                 $out[] = 'start';
  1481.                 $allyname = resolveUsername($matches[1]);
  1482.                 $playernames = array($matches[1],$matches[2]);
  1483.             }
  1484.             else
  1485.             {
  1486.                 $out[] = 'player '.$matches[2];
  1487.                 $out[] = 'foe-player '.$matches[1];
  1488.                 $out[] = 'start';
  1489.                 $allyname = resolveUsername($matches[2]);
  1490.                 $playernames = array($matches[2],$matches[1]);
  1491.             }
  1492.             $english = true;
  1493.         }
  1494.         else if (preg_match('/^\<([^<>]+) won the battle!\>$/', $line, $matches))
  1495.         {
  1496.             $winner = $matches[1];
  1497.         }
  1498.         else if (preg_match('/^\<Tie between ([^<>]+) and ([^<>]+)!\>$/', $line, $matches))
  1499.         {
  1500.             $winner = true;
  1501.         }
  1502.         else if (preg_match('/^Hit ([0-9]) times!$/', $line, $matches))
  1503.         {
  1504.             $out[] = '  r-hit-count '.$movetarget.' '.$matches[1];
  1505.         }
  1506.         else
  1507.         {
  1508.             $out[] = 'unknown-effect '.$newline;
  1509.         }
  1510.         if ($returnNow)
  1511.         {
  1512.             return false;
  1513.         }
  1514.     }
  1515.    
  1516.     if (!$english)
  1517.     {
  1518.         $convertNotDone = false;
  1519.         if (@$_REQUEST['dev']) echo '"'.implode("\n", $text).'"';
  1520.         return array('error Replay file must be an English Pokemon Online replay file.');
  1521.     }
  1522.     if ($switchcounter === 104)
  1523.     {
  1524.         return array('error Double battles are not supported (neither are triples, for that matter).');
  1525.     }
  1526.     if ($switchcounter === 106)
  1527.     {
  1528.         return array('error Triple battles are not supported (neither are doubles, for that matter).');
  1529.     }
  1530.    
  1531.     if ($winner === true) $out[] = 'tie';
  1532.     else if ($winner) $out[] = 'win '.$winner;
  1533.     else $out[] = 'premature-end';
  1534.    
  1535.     foreach ($currentpokemon as $poke)
  1536.     {
  1537.         $oldlinesoffset++;
  1538.         array_unshift($out, 'pokemon '.$poke);
  1539.     }
  1540.     {
  1541.         $oldlinesoffset++;
  1542.         array_unshift($out, 'gen '.$GLOBALS['gen']);
  1543.     }
  1544.     if ($english === 'warn' && $switchcounter !== 102)
  1545.     {
  1546.         $oldlinesoffset++;
  1547.         array_unshift($out, 'warning This is a spectator replay. Crashes may occur since the game may have been joined midway-through.');
  1548.     }
  1549.    
  1550.     return $out;
  1551.  
  1552. }
  1553.  
  1554.  
  1555. function convertById($name)
  1556. {
  1557.     global $REPLAYS;
  1558.     if (!$REPLAYS[$name])
  1559.     {
  1560.         return;
  1561.     }
  1562.     $text = file_get_contents("uploads/$name.html");
  1563.    
  1564.     $out = pokeConvert($text);
  1565.    
  1566.     if (substr($out[0],0,6) === 'error ')
  1567.     {
  1568.         return $out;
  1569.     }
  1570.    
  1571.     $fp = fopen("uploads/$name.js",'w');
  1572.    
  1573.     fwrite($fp, "var newlog = [\n");
  1574.     foreach ($out as $line)
  1575.     {
  1576.         fwrite($fp, "'".addcslashes($line,"'\\")."', \n");
  1577.     }
  1578.     fwrite($fp, "''];");
  1579.     fclose($fp);
  1580.    
  1581.     $fp = fopen("uploads/$name.txt",'w');
  1582.     foreach ($out as $line) fwrite($fp, $line."\r\n");
  1583.     fclose($fp);
  1584.    
  1585.     $REPLAYS[$name]['unidentified'] = array();
  1586.     $REPLAYS[$name]['tags'] = array();
  1587.     $lsreflect = array();
  1588.     foreach ($out as $line)
  1589.     {
  1590.         if (startsWith($line, '  r-bounce-back ') && strpos($line, ' MagicCoat '))
  1591.             $REPLAYS[$name]['tags'][] = 'Magic Coat';
  1592.         if (startsWith($line, '  r-transform '))
  1593.             $REPLAYS[$name]['tags'][] = 'Transform';
  1594.         if (startsWith($line, 'move ') && strpos($line, ' RelicSong '))
  1595.             $REPLAYS[$name]['tags'][] = 'Relic Song';
  1596.         if (endsWith($line, ' LightScreen'))
  1597.             $lsreflect['ls'] = true;
  1598.         if (endsWith($line, ' Reflect'))
  1599.             $lsreflect['r'] = true;
  1600.         if (endsWith($line, ' LightScreen end'))
  1601.             $lsreflect['ls'] = false;
  1602.         if (endsWith($line, ' Reflect end'))
  1603.             $lsreflect['r'] = false;
  1604.         if (startsWith($line, 'unknown-effect '))
  1605.             $REPLAYS[$name]['unidentified'][] = $line;
  1606.         if (startsRemove($line, 'error '))
  1607.             $REPLAYS[$name]['error'] = $line;
  1608.         if (startsRemove($line, 'warning '))
  1609.             $REPLAYS[$name]['tags'][] = 'Warning: '.$line;
  1610.        
  1611.         if ($lsreflect['r'] && $lsreflect['ls'])
  1612.         {
  1613.             $REPLAYS[$name]['tags'][] = 'Dual Screens';
  1614.             $lsreflect = array();
  1615.         }
  1616.     }
  1617.     if (!$REPLAYS[$name]['unidentified']) unset($REPLAYS[$name]['unidentified']);
  1618.     persist_save('REPLAYS');
  1619.     return $out;
  1620. }