JeuWeb - Crée ton jeu par navigateur
Systèmes de combats, la limite des boucles - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Systèmes de combats, la limite des boucles (/showthread.php?tid=7396)



Systèmes de combats, la limite des boucles - LoKeD - 09-06-2015

Bonjour, une petite question me taraude en ce qui concerne les boucles.

Tout d'abord, je suis en pleine création d'un script de bataille. Je souhaite pouvoir gérer chaque unité une par une, mais j'aimerais tout de même que ces combats ne soient pas du genre à 10v10. Je cherche du combat de masse, histoire qu'il y ait de l'action ! Du coup, quelles seraient à votre avis les limites maxi des while, for, foreach afin de ne pas trop surcharger le serveur ?

Petit bonus : Comment vous y prendriez-vous au niveau de la structure pour réaliser ceci ?


RE: Systèmes de combats, la limite des boucles - Xenos - 09-06-2015

Yop

pour ma part, je tenterai de voir (parce que j'adore ce genre de défi :p) s'il n'existe pas une formule directe plutôt qu'itérative. C'est à dire est-ce qu'il existe une fonction mathématique qui donne directement le résultat du combat (c'est parfaitement envisageable, même s'il devient délicat de manipuler des fonctions dont les entrées/sorties sont des vecteurs de dimension 100!).

Après, en cas d'échec, je ferai un système de groupe: je ne fais pas une bataille de NvsP unités, mais une bataille de (N groupes homogènes d'unités)vs(P groupes homogènes). L'avantage est alors de pouvoir faire des batailles de 10k vs 10k tout comme on fait des batailles de 10vs10: on ne simule pas chaque unité, mais on groupe toutes les unités identiques dans un seul sac, et on fait des combats de sac.

Enfin, je testerai. Car PHP (et mieux, MySQL, ou Java) tiennent très bien les boucles internes (des boucles sans appel de fonction pour PHP).
De plus, OVH a un bon score par rapport à ma propre machine, et de façon surprenante, certaines pages sont plus rapides en ligne qu'en local !

Structurellement, la question est assez vague, mais je dirai que j'aurai un code (class ou classes) dédié aux combats, auquel je passe ma liste d'unités (soit déjà en sacs soit en vrac). Ce code fait la simulation de combat, en distingant bien le code simulateur du code calculateur. C'est à dire une classe qui se charge de faire la simulation, mais qui ne sert à rien car elle n'a pas les formules de calcul, et une classe qui a les formules de calcul (mais qui ne sert à rien sans le simulateur qui les applique).
Sans oublier des logs intermédiaires (dans le Simulateur) pour savoir comment la simulation se déroule (sinon, les résultats seront surprenant, sans qu'on sache pourquoi!).


RE: Systèmes de combats, la limite des boucles - LoKeD - 09-06-2015

Tout d'abord je tiens à te remercier de ton intervention.


J'ai déjà pensé au cas de Groupe vs Groupe, mais le soucis est que je ne sais pas comment gérer les unités au cas par cas dans un groupe. Je vais exposer mon problème, sait-on jamais, peut-être auras-tu une base à me transmettre pour y parvenir.

En combat de masse j'ai procédé ainsi sur mes derniers tests :
Code PHP :
<?php 
$uniteP1
= ['atk'=>5, 'hp' =>25, 'nb'=>6200];
$uniteP2= ['atk'=>6, 'hp' =>35, 'nb'=>4500];

$totalP1atk = $uniteP1['nb']*$uniteP1['atk']; // On définit l'attaque totale de l'armée de P1
$totalP2hp = ($uniteP2['nb']*$uniteP2['hp'])-$totalP1atk; // On définit les pv restants de l'armée de P2
$uniteP2['nb'] = ($totalP2hp/$uniteP2['hp']); // On fonction de nombre de pv perdus, on attribut un nouveau nombre d'unités vivantes

Mais les unités organiques se régénérerons à chaque fin de tour de Xpv ou X%pvMax (à définir), et le hic, en ayant testé ce système, était que seule la dernière unité pouvait se régénérer et toutes les autres restaient à 100% de leur pv. Du coup, je trouve cette idée de régénération totalement inutile s'elle ne touche qu'une seule unité dans le lot (d'où la recherche du cas par cas qui m'intéresse).

En ce qui concerne le score de la machine, je suis actuellement chez 1and1, je n'ai pas encore eu l'occasion de tester l'efficacité de leurs machines. :heu:

Je cite "Enfin, je testerai. Car PHP (et mieux, MySQL, ou Java) tiennent très bien les boucles internes (des boucles sans appel de fonction pour PHP).". Quand tu parles d'une fonction dans une boucle, c'est bien ce genre de chose que tu penses ?

Code PHP :
<?php 
while() { function($param1, $param2 etc.)}



RE: Systèmes de combats, la limite des boucles - Xenos - 09-06-2015

Oui, c'est ce genre de chose que j'ai en tête. PHP ayant des appels de fonctions assez lourd, mieux vaut créer des fonctions traitant des groupes d'objet (quitte à parfois leur passer un array avec juste un objet) plutôt que de faire une fonction traitant un objet et l'appeler en boucle. D'ailleurs, cette approche est valable dans tous les langages, elle est juste encore plus efficace en PHP.



{A mon propre avis, ma réponse n'est pas claire, il faudrait que je la mette au propre dans un article illustré}

Oui, seule la dernière unité se regénère car dans ta simulation, tu as en fait attribué les dégâts aux mêmes unités (toutes mortes du coup), pendant que les autres unités n'étaient pas touchées. L'autre approche pourrait être de répartir totalement les dégâts sur toutes les unités, dans ce cas la regénération sera intéressante mais toutes les unités mourront en même temps (au dernier tour).
L'approche intermédiaire, vers laquelle je me dirigerai (j'avais d'ailleurs fait ce genre d'approche sur eclerd, pour l'âge de la population) consiste à fixer une courbe de répartition des dégâts. Dans l'idée:
• J'ai un groupe de N unités, et je veux répartir une donnée (ici la santé) sur ces unités
• Je considère que les unités sont "classées": l'unité 0 sera celle avec la donnée la plus basse (quasi morte) et l'unité N sera celle avec ma donnée la plus haute (la plus en forme)
• Je fixe la valeur de la donnée pour l'unité 0, pour l'unité N et je fixe une fonction de répartition de 0 à N (fonction croissante)
• Quand les unités perdent de la valeur de cette donnée, j'utilise la fonction de l'intégrale pour répartir cette perte


Comme je suis sûr que c'est abscons ( Smile ), je vais prendre un exemple:
→ J'ai N=1000 unités, de santé 100. Donc, initialement, toutes les unités ont 100 pts de vie (100.000 pts de vie au total). Je vais considérer que la répartition de la santé est linéaire. Donc, pour l'unité numéro n, sa santé sera SanteUnite0 + (SanteUnite{N-1}-SanteUnite{0})/N*n (rappel: K=(SanteUnite{N-1}-SanteUnite{0})/N est la pente de la droite, une feuille et un diagramme peuvent aider Wink ).
→ Le total de santé d'un groupe d'unité est de TotalSante = (SanteUnite{N-1}-SanteUnite{0})*N/2+SanteUnite{0}*N (c'est là que l'intégrale intervient)
→ Au début, SanteUnite{0} = SanteUnite{N-1} = 100 On pourra faire des unités blessés après si besoin.
→ J'ai un combat qui se déroule, et les dégâts s'élèvent à 15.000 points.
→ Du coup, je reprends TotalSante = 100.000-15.000 = 85.000, TotalSante = (SanteUnite{N-1}-SanteUnite{0})*N/2+SanteUnite{0}*N, et j'en déduis 85.000 = (SanteUnite{N-1}-SanteUnite{0})*N/2+SanteUnite{0}*N
→ Je centre mon équation (c'est un peu la magie des maths là...!) : TotalSante = K/2*(N-1)²+(lambda-N*K/2)*(N-1) avec K=(SanteUnite{N-1}-SanteUnite{0})/N
→ N>>1 donc je peux considérer que N-1~N (ce genre d'approximation est hyper-utile, car cela simplifie énormément les calculs)
→ Du coup, lambda = TotalSante / N
→ J'ai alors une fonction de répartition de la santé sous la forme f(n)=TotalSante/N + K*(n-N/2)
→ Ne reste plus qu'à calculer une valeur de K qui représentera la répartition des dégats, et voilà! Comme on a classé les unités par ordre croissant, on fixe K>=0, et comme l'unité N ne peut pas "gagner" de santé, on a SanteUnite{N}=f(N)=TotalSante/N + K*(N-N/2)<=SantePrecedente{N} donc K <= (100 - TotalSante/N)/(N-N/2) = (100 - TotalSante/N)*2/N
→ Hop, on synthétise, et on a:

• SanteUnite{N/2} = (SantePrecedente-Degats)/N
• 0 <= K <= 2*(SantePrecedente{N} - (SantePrecedente-Degats)/N)/N


Bon, je sais pas si c'est plus clair en fait... Ca mériterait un article propre dédié ^^
A noter, la santé de certaines unités pourra être négative, ce qui représente une unité attaquée par plusieurs ennemis en même temps.

Une autre façon de faire (qui sera peut être plus simple) serait de répartir le groupe en deux: une partie des unités meurt, encaissant des dégâts, et l'autre partie se répartie les dégâts de façon linéaire. C'est à dire que les unités de 0 à K sont toutes mortes, et les unités de K à N ont une vie de 0 à 100 (vie(n)=100*(n-K)/N).


RE: Systèmes de combats, la limite des boucles - LoKeD - 10-06-2015

Alors, n'étant déjà pas très à l'aise avec les fonctions, je vais essayer de détailler tout ceci sur papier à l'occasion histoire de pouvoir mieux imprégner les formules et les correspondances. Je te remercie en tout cas pour cette base ! ^^ Une fois que j'aurais tout déchiffré, ça devrait aller mieux.

Penses-tu qu'il serait également possible de réutiliser cette formule pour les boucliers ? Certaines unités possèdent un bouclier qu'il faut éliminer avant d'entamer les pv. Et une fois de plus, avec mon anciens système, il fallait descendre l'intégralité du bouclier de toutes les unités pour entamer les pv. xD Mais là, j'avoue qu'à mon avis... la formule doit être encore plus complexe. Je regrette de ne pas avoir fait des maths. x)


RE: Systèmes de combats, la limite des boucles - Xenos - 10-06-2015

C'est un mécanisme mathématique générique (des stats en fait), donc c'est applicable à n'importe quel type de population ("suffisamment nombreuse"), pour n'importe quelle type de donnée (vie, bouclier, munitions,...) qui soit propre à chaque individu de la population.


RE: Systèmes de combats, la limite des boucles - LoKeD - 17-06-2015

Je vais analyser ceci quand j'aurais le temps dans ce cas ! Big Grin Pour le moment, mon projet est en pause.