I'm trying to figure out the best design pattern to use for managing a "competition" between two interacting objects. For example, if I want to have a Fox
class that chases a Rabbit
class through a simple environment. I want to let them "compete" and find out which one wins. Eventually it would become a teaching tool that students can use to experiment with inheritance and other OO programming skills.
Is there an established design patter for this use case?
Here's the best I could come up with: one class to represent the environment that hosts both other objects. I'm keeping it very simple and assuming the animals only run in straight lines and the fox catches the rabbit if he gets close enough to bite the rabbit. Here is some code demonstrating what I'm describing. I used PHP because I can write it quickly, but I don't want to focus on the specifics of the language. My question is really about the design pattern / architecture.
class Forrest() {
public $fox;
public $rabbit;
public $width = 100; //meters?
public $length = 100;
__construct() {
$this->fox = new Fox();
$this->rabbit = new Rabbit();
$this->theChase();
}
public function theChase() {
while (!$this->rabbit->isBitten) {
$this->rabbit->react($fox);
$this->fox->react($rabbit);
}
log('The fox got the rabbit!');
}
}
abstract class Animal() {
public $speed;
public $hasTeeth = false;
public $position;
public $direction;
public $isBitten = false;
public function run($distance) {
// update coordinates based on direction and speed
}
public function bite($someone) {
if (isCloseEnough( $someone ) && $this->hasTeeth) {
$someone->isBitten = true;
log(get_class($this) . ' bit the ' . get_class($someone)); //the Fox bit the Rabbit
}
}
public abstract function react($someone);
}
class Rabbit extends Animal {
__construct() {
$this->speed = 30;
$this->position = [0,0];
$this->direction = 'north';
log(get_class($this) . ' starts at 0,0');
}
public react($fox) {
//avoid the fox
}
}
class Fox extends Animal {
__construct() {
$this->speed = 20;
$this->position = [100,100];
$this->direction = 'south';
log (get_class($this) . ' starts at 100,100');
}
public react($rabbit) {
//try to catch the rabbit
}
}
There are two immediate problems I see with this approach:
This architecture results in sequential, alternating actions. In other words, first the rabbit does something then the fox does something then the rabbit does something... This is more like a card game where each player takes turns moving. It would be more interesting if both objects were able to react simultaneously.
There is not yet a system for limiting the amount of activity per "turn". There needs to be some sort of restriction on what can happen in a single "turn" to keep it interesting. Otherwise the fox could simply
run()
run()
run()
...run()
until it catches the rabbit on it's first turn.
There are probably other problems that I haven't noticed yet. I suspect that the answer to both (1) and (2) above is some sort of event system that allows action from one animal to trigger action from the other and visa versa. I also think there may need to be some representation of time associated with each action, but I'm not entirely sure.