views:

2176

answers:

3

Is it possible to include one function inside another? To learn functions, I'm trying to create a combat sequence using PHP. The sequence would look like this:

  1. Dice would roll, assigning numbers to variables;
  2. Hero1 attack results are printed;
  3. Dice would roll, assigning numbers to variables;
  4. Hereo2 attack results are printed;
  5. Dice would roll, assigning numbers to variables;
  6. Hero3 attack results are printed.

The dice rolling would be an automated function. Here is the code:

<?
rollSim();
combatSim();

function rollSim() {
    $hAttack = rand(1,20);
    $mDefend = rand(1,20);
    $mAttack = rand(1,20);
    $hDefend = rand(1,20);
    $mDamage = rand(10,25);
    $hDamage = rand(1,20);
} // end rollSim

function combatSim() {
    rollSim();
    if ($hAttack>$mDefend) {
        print "Hero hit monster for $hDamage damage.<br>";
    } else if ($hAttack<=$mDefend) {
        print "Hero missed monster.";
    }
} // end combatSim

?>
A: 

You can call functions from one another, certainly... but I think you want to use the scope of one in another, correct?

Sharing scope is a messy business. You're better off passing arguments.

Kalium
+5  A: 

Your rollSim() function should return the rolled numbers rather than setting some variables and trying to use them in your other function. I would return them in an associative array, like this:

function rollSim() {
    $roll['hAttack'] = rand(1,20);
    $roll['mDefend'] = rand(1,20);
    $roll['mAttack'] = rand(1,20);
    $roll['hDefend'] = rand(1,20);
    $roll['mDamage'] = rand(10,25);
    $roll['hDamage'] = rand(1,20);

    return $roll;
}

function combatSim() {
    $roll = rollSim();

    if ($roll['hAttack'] > $roll['mDefend']) {
        print "Hero hit monster for {$roll['hDamage']} damage.<br>";
    } else if ($roll['hAttack'] <= $roll['mDefend']) {
        print "Hero missed monster.";
    }
}
yjerem
Thanks for answer; this is very very helpful. Quick follow-up question - will I be able to have the function "re-roll" each time? So, for example I would need a separate set of dice rolls for hero2 and hero3. Thank you again to everyone who has responded.
The body of the second if in combatSim isn't needed. (I know you copied the OP's if; just wanted to mention.)
strager
@Matt, Pass the results of the rolls as parameters to combatSim.
strager
Yes, every time you call rollSim() you'll get a new set of dice rolls. You could do it like this for example: $hero1 = rollSim(); $hero2 = rollSim(); $hero3 = rollSim(); (And if there are any more heroes than this, make an array of heroes instead!)
yjerem
This is great. I will need to work backwards through all this, but I've got everything I need now to keep learning and to get this to work. Thanks very much!
A: 

No, you can't really do what you're asking. Even if you embedded the declaration of rollSim() inside the definition of combatSim() (which you can do, that's legal but has no real effects), the variables you're setting in rollSim() would still be local to it and inaccessible by combatSim().

You need a better way of passing around the information you're concerned with. Jeremy Ruten details a good way. Another way would be to define an object that's responsible for modeling your combat event and have rollSim() and combatSim() both be methods on it.

class myCombat {

    private $hAttack;
    private $mDefend;
    private $mAttack;
    private $hDefend;
    private $mDamage;
    private $hDamage;

    function rollSim() {
        $this->hAttack = rand(1, 20);
        $this->mDefend = rand(1, 20);
        $this->mAttack = rand(1, 20);
        $this->hDefend = rand(1, 20);
        $this->mDamage = rand(10, 25);
        $this->hDamage = rand(1, 20);
    }

    function combatSim() {
        $this->rollSim();
        if($this->hAttack > $this->mDefend)
            echo 'Hero hit monster for ' . $this->hDamage . ' damage.<br />';
        else
            echo 'Hero missed monster';
    }

}

$combat = new myCombat;
$combat->combatSim();
chaos