Author Topic: Combat system script problem, Fatal error: Allowed memory size  (Read 738 times)

Offline Vesparion

  • Level 1
  • *
  • Posts: 2
  • Reputation: +0/-0
    • View Profile
if($_POST) {
   if($_POST['action'] == 'Attack') {
      require_once 'stats.php';         // player stats
      require_once 'monster-stats.php';   // monster stats
      // to begin with, we'll retrieve our player and our monster stats
      $query = sprintf("SELECT id FROM users WHERE UPPER(username) = UPPER('%s')",
               mysql_real_escape_string($_SESSION['username']));
      $result = mysql_query($query);
      list($userID) = mysql_fetch_row($result);
      $player = array (
         name      =>   $_SESSION['username'],
         attack       =>   getStat('atk',$userID),
         defence      =>   getStat('def',$userID),
         curhp      =>   getStat('curhp',$userID)
      );
      $query = sprintf("SELECT id FROM monsters WHERE name = '%s'",
               mysql_real_escape_string($_POST['monster']));
      $result = mysql_query($query);
      list($monsterID) = mysql_fetch_row($result);
      $monster = array (
         name      =>   $_POST['monster'],
         attack      =>   getMonsterStat('atk',$monsterID),
         defence      =>   getMonsterStat('def',$monsterID),
         curhp      =>   getMonsterStat('maxhp',$monsterID)
      );
      $combat = array();
      $turns = 0;      
      while($player['curhp'] > 0 && $monster['curhp'] > 0) {
         if($turns % 2 != 0) {
            $attacker = &$monster;
            $defender = &$player;   
         } else {
            $attacker = &$player;
            $defender = &$monster;
         }
         $damage = 0;
         if($attacker['attack'] > $defender['defence']) {
            $damage = $attacker['attack'] - $defender['defence'];   
         }
         $defender['curhp'] -= $damage;
         $combat[$turns] = array(               <----- Error
            attacker   =>   $attacker['name'],
            defender   =>   $defender['name'],
            damage      =>   $damage
         );
         $turns++;


Error:

Fatal error: Allowed memory size of 52428800 bytes exhausted (tried to allocate 35 bytes)

The error refers to line :
...
$combat[$turns] = array(
...



php.ini is set to 64 mb

Offline dsheroh

  • Level 21
  • *
  • Posts: 235
  • Reputation: +6/-0
  • Perl Vicar
    • View Profile
    • Psi Rangers
Re: Combat system script problem, Fatal error: Allowed memory size
« Reply #1 on: March 19, 2010, 06:18:10 AM »
I suspect that, when it dies, the value of $turns is extremely large.  If neither side has an attack higher than the other's defense (e.g., the player and the monster both have attack 1 / defense 2 - or even attack 1 / defense 1), then this will be an infinite loop of "Player does 0 damage.  Monster does 0 damage.  Player does 0 damage...", so it would just keep running forever if not for the 'combat' array growing to consume all available memory first.

To resolve this and prevent it from happening in the future, you should implement a limit on the maximum number of turns a combat is allowed to run before being ended and declared a draw.

You might also want to think about adding some randomness in the damage done so that you can't just look at your stats, look at a monster's stats, and immediately know who will win, how many rounds it will take, and exactly how many HP the winner will have left.  If you don't want to add randomness, then you should determine the result in a single set of calculations instead of looping; it will be friendlier to system resources and less prone to errors of this sort.

Offline Vesparion

  • Level 1
  • *
  • Posts: 2
  • Reputation: +0/-0
    • View Profile
Re: Combat system script problem, Fatal error: Allowed memory size
« Reply #2 on: March 19, 2010, 06:58:03 AM »
Quote
determine the result in a single set of calculations

Could you give me an example ?

Offline dsheroh

  • Level 21
  • *
  • Posts: 235
  • Reputation: +6/-0
  • Perl Vicar
    • View Profile
    • Psi Rangers
Re: Combat system script problem, Fatal error: Allowed memory size
« Reply #3 on: March 19, 2010, 07:35:20 AM »
Quote
determine the result in a single set of calculations

Could you give me an example ?

Sure, I just didn't break it down into math in the previous post because I wasn't sure whether you were intending to be non-random permanently or if the fixed calculations were just a placeholder until you're ready to add randomness.

For the combat model in the code you posted, if PA is the player's attack rating, PD is player's defense, PH is player's (starting) HP, and MA/MD/MH are the corresponding monster stats:

First filter out the trivial cases:
  • If PD >= MA and MD >= PA, then neither side can hurt the other and the combat will be a draw.
  • If PD >= MA and MD < PA, Player will win without taking damage.
  • If MD >= PA and PD < MA, Monster will win without taking damage.

When both sides can hurt each other (i.e., MA > PD and PA > MD), then you need to do some actual calculations:
  • Player will inflict PA - MD damage each round, killing the monster in MH / (PA - MD) rounds, rounded up.  Call this number of rounds PWT (Player Win Time).
  • Monster will inflict MA - PD damage each round, killing the player in PH / (MA - PD) rounds, also rounded up.  Call this MWT.
  • If PWT <= MWT, Player wins in PWT rounds and suffers (MA - PD) * (PWT - 1) damage.  The -1 is because, in the final round of combat, the monster will die before it gets to attack.
  • If MWT < PWT, Monster wins in MWT rounds and suffers (PA - MD) * MWT damage.

 


SimplePortal 2.3.3 © 2008-2010, SimplePortal