Une fois les bases du jeu établies, c'est là que ça devient intéressant. Nous sommes en mesure de générer un combat entre deux adversaires, en tenant compte d'une force arbitraire et d'un facteur de défense. Maintenant, il est temps de voir comment faire s'affronter plus d'un adversaire, dans une bagarre du type "royal rumble" où les combattants sont éliminés un par un et où seul le dernier combattant sera désigné comme vainqueur. J'avais trouvé cette analogie avec la lutte mais comme je suis loin d'être amateur de cette discipline sportive, je crois que je pourrais dire que c'est aussi comme dans les films Highlander : ils s'éliminent entre eux jusqu'à ce qu'il n'en reste qu'un.
Allons-y pour un combat à plusieurs joueurs où chacun tente de sauver sa peau. À cette étape-ci, nous n'aurons pas à modifier la classe Fighter. Tout se passera dans l'arène.
On commencera par générer un nombre de combattants à l'aide d'une boucle for sur le constructeur. Pour les fins de l'exercice, je générerai un nom générique pour chaque combattant en utilisant l'itérateur $i et je les empilerai dans la liste $fightersList. Au fur et à mesure que les combattants tomberont au combat, on les retirera de cette liste.
// modifiez cette constante pour plus de combattantsAvec plus de deux combattants, on voudra éviter d'ajouter une vérification de la fonction isKnockOut() sur chaque objet. Il sera préférable de trouver un autre moyen qui prendra en charge un nombre variable de combattants.
DEFINE('NB_FIGHTERS', 10);
for($i=1 ; $i<=NB_FIGHTERS ; $i++){
$fightersList[] = new Fighter('Fighter # ' . $i);
}
// ne plus faire celaAvant la boucle while, assignez le compte initial de la liste à une variable qui nous servira à connaître le nombre de combattants encore en état de se battre.
while( !( $player1->isKnockOut() || $player2->isKnockOut() ) ){
$fightersLeft = count($fightersList);La boucle while pourra être remplacée ainsi :
// tant qu'il reste plus d'un combattant, il peut y avoir face à facePour une raison que j'ignore, si je n'utilise pas la fonction shuffle() sur la liste avant d'appeler array_rand(), ce sera Fighter #1 qui remportera les combats à 99% du temps. L'environnement PHP sur lequel je développe présentement est PHP 5.2.8. La documentation d'array_rand() indique à partir de PHP 5.2.10, le tableau résultant des clés ne sera plus mélangé. Pourtant, il semble y avoir un défaut. Peut-être est-ce dû à PHP version Windows ?
while( $fightersLeft > 1 ){
shuffle($fightersList);
list($attacker, $defender) = array_rand($fightersList, 2);
$damage = $fightersList[$attacker]->hit($fightersList[$defender]);
if($damage > 0){
echo $fightersList[$attacker]->getName() . ' hits ' . $damage . ' HP on ' . $fightersList[$defender]->getName() . "\n";
}
else{
echo $fightersList[$attacker]->getName() . ' misses ' . $fightersList[$defender]->getName() . "\n";
}
if( $fightersList[$defender]->isKnockOut() ){
echo '<strong>' . $fightersList[$defender]->getName() . ' is KNOCK OUT</strong>' + "\n";
// retirer le perdant de la liste des combattants
unset($fightersList[$defender]);
$fightersLeft--;
}
// lorsqu'il en reste 1, l'attaquant est automatiquement le gagnant
if($fightersLeft == 1){
$winner = $fightersList[$attacker];
}
}
Pour déterminer le gagnant, j'aurais pu aussi vérifier chaque objet pour voir s'il était KO et conserver une référence au seul qui ne l'est pas :
$winner = null;Mais en conservant le compte de $fightersLeft et en retirant les perdants de la liste, on sait que si sa valeur est 1, il ne restera qu'un objet dans la liste de combattants actifs, donc le gagnant (ça éviter aussi d'appeler count() à chaque fois).
foreach($fightersList as $fighter){
if(!$fighter->isKnockOut()){
$winner = $fighter;
}
}
Pour la prochaine étape, pourquoi ne pas tenter de diviser les combattants en deux clans ennemis pour générer une vraie guerre ?