Einzelkämpfe in großer Schlacht berechnen

Sandra Haupt

Grünschnabel
Hallo Leute,

ich bitte bei dem folgenden Problem um Eure Hilfe:

Ich möchte die einzelnen Mann gegen Mann Kämpfe zweier Armeen berechnen. Als Beispiel habe ich Armee A mit 100 Soldaten und Armee B mit 50 Soldaten aus meiner MySQL Datenbank geordnet nach deren Initiative-Wert in jeweils einem bidimensionales Array ausgelesen. Das Array mit den 100 Soldaten besteht aus 100 Reihen in der jeweils ein weiteres Array mit den individuellen Kampfwerten (Initiative, Lebenspunkte, Angriff, Verteidigung) dieses Soldaten gespeichert ist.

Ich möchte nun, dass der Soldat mit dem höchsten Initiative Wert der einen Armee, einen zufälligen Soldaten der anderen Armee angreift, aber nur wenn der andere Soldat noch über Lebenspunkte verfügt. Danach ist der Soldat an der Reihe mit dem zweithöchsten Initiativewert usw. Im Verlaufe der Schlacht werden immer mehr Soldaten über keine Lebenspunkte mehr verfügen. Irgendwann werden in einer Armee keine Soldaten mehr Lebenspunkte haben und der Kampf endet.

Wie kann ich diese Simulation am einfachsten berechnen lassen? Meine bisherigen Überlegungen gehen in die oben beschriebene zwei bidimensionale Array Richtung, allerdings reichen meine Programmierkenntnisse nicht aus, um z.B. bei einem Angriff von einem Soldaten A einen zufälligen Soldaten aus B auszuwählen und gleichzeitig noch vorab zu überprüfen, ob dieser noch über Lebenspunkte verfügt. Auch das wechselseitige Durchlaufen der bidimensionalen Arrays, weil ständig ein Soldat der anderen Armee einen höheren Initiative Wert haben könnte, bereit mir Schwierigkeiten.

Vielen Dank, Sandra
 
Morgen!

Da es sich wohl um ein Browsergame handelt kann ich dir nur raten diese Berechnung in ANSI C, C++ durchführen zu lassen.

Es gibt viele Gründe, zum Beispiel das die Berechnungen in einer C Variante um einen Tick schneller ablaufen, da nicht erst PHP angesprochen werden müssen. Zudem könnte die Berechnung so lange laufen das es zu einem TimeOut kommt und es zu keinem vollständigen Ergebnis kommt.
Dann ist die Performance unter C besser, was sich auf die Load des Servers auswirkt.

Zur Berechnung muss natürlich vorliegen, welche Fahigkeiten, Lebenspunkte und welchen Character der Soldat hat.
Ist er Angriffslustig oder eher Abwartend (Character), hat er ein Messer oder ein Gewehr in der Hand und wie genau kann er damit arbeiten (Fähigkeiten) und wieviel Lebenspunkte hat er und wieviel nach einem Treffer, dabei muss man auch wissen wieviel Schaden eine Waffe anrichtet.

Dann sollte man anfangen, wenn diese Werte in einem Array oder ähnliches vorliegen. Per Random einen Soldaten auswählen, der volle Energie hat (Es wird wohl kein Soldat der fast 0 Lebenspunkte hat an der Front stehen). Die gleiche Auswahl bei den Gegnern. Dieser Kampf wird berechnet, indem man per Zufallswert oder nach Charactereigenschaft schaut, wer den ersten Schlag macht. Es erfolgt eine Berechnung des Schadens durch den Schlag und es folgt der nächste Schlag.
Usw usw usw...

Ich schreibe extra keine Codezeilen, da ich nicht weiss wie deine Daten aus der DB vorliegen und zudem der Code sehr sehr sehr sehr lang wird und dann in PHP nicht wirklich (in meinen Augen) sinn macht.

MfG
Andreas
 
Original geschrieben von Mairhofer
Zudem könnte die Berechnung so lange laufen das es zu einem TimeOut kommt und es zu keinem vollständigen Ergebnis kommt.

Wenn das ganze so lange dauern sollte, sollte man das Projekt evt. etwas kleiner dimensionieren, meinst du nicht? :p
Zudem halte ich es für Quatsch, dass die Berechnungen so lange dauern sollten, sofern das Spiel nicht mit 5.000 Spielern auf einem PII-233 läuft. Wenn dennoch Zweifel bestehen solltest du es mit Perl oder JSP versuchen, C halte ich da für die falsche "Schnittstelle".
 
Ich berufe mich da eher auf Aussagen von Spieleentwicklern aus Browsergames Foren, die Ihre Berechnungen zum grössten Teil in C durchführen.
Frag mich nicht wieso, aber die machen es.

Die Dimensionierung kann man nicht immer so einfach runter drehen.
Berechnet man einen Kampf nur anhand der Stärken der Armee wirds unrealistisch und unfair, da es keine "sensationen" gibt. Das ist genauso, als wenn man einen Fussballmanager macht und Bayern dauernd gewinnt, weil die am meisten Geld in die Mannschaft gesteckt haben.
Daher werden gute Fussballmanager mit sau vielen Optionen bestückt, um einen fairen Spielverlaif zu garantieren. Heimstärke, Abwehr/Sturmverhalten jeden Spielers, Übersicht, Passgefühl, Freistoss.... eine Endlos lange liste.
Durch dieses Realismus erreicht man die Spieler und kann somit auf ein erfolgreiches Browsergame zurückschliessen.
Das ganze kann man nun vom Fussball zum Kampf übertragen. Eine Armee, die viele Waffen hat und viel Geld gewinnt nicht immer, sie etliche Beispiele der Amerikaner (ich enthalte eine eigene Wertung!).
Die Threadstarterin spricht von einer GROSSEN Schlacht und einer Simulation, für mich ist damit gesagt, jeder Soldat und jede Stärke wird mit einberechnet. Ansonsten wäre es nur eine "Arcade" Version (wenn es sowas gibt).

So viel Text, wenig Inhalt, aber: ein Browsergame zeichnet sich nicht nur durch viele Features aus, wie 100 Gebäude bauen, 300 Typen Soldaten und 50 fahrzeuge, sondern der Realismus ist gefragt. Und ich hab selten einen Kampf/Krieg gesehen, wo 5 Einheiten in den Kampf ziehen und sich bekriegen (ausser bei den Nachbarskindern die wieder Räuber und Gandarm spielen)

Warum ich C genannt habe ist, das es halt in Maschinencode compiliert wird und somit (in meinen Augen) schneller berechnet werden kann. Applikationen in JSP und Perl müssen ja quasi erst wieder durch den Compiler.
ok ich hab da keine Ahnung wirklich von, wie die Arbeiten, aber C kann ich wenigstens ein bischen ;)

So noch mehr Text, keine richtige Antwort wird mehr OT merk ich gerade.
Ich hör dann mal lieber auf,
MfG
Andreas
 
Hallo Mairhofer,

es handelt sich tatsächlich um ein Browsergame und die Soldaten haben auch noch mehr Eigenschaften als die von mir beschriebenen, z.B. noch Zielen, Ausweichen, Rüstung, Schild, Waffenart, mehr als eine Waffe, mehr als eine Attacke usw. Ich denke, dass PHP von der Performance ausreichen wird, weil nur eine Kampfrunde je Minute abgewickelt werden wird. Dies macht den Kampf realistischer, der Spieler erhält die Möglichkeit Reserven einzubringen bzw. andere Spieler können später auf der einen oder anderen Seite in den Kampf einsteigen.

Die Daten erhalte ich aus einer MySQL Datenbank. Ich stecke einfach an der Stelle fest, wo ich beide Armeen jeweils in einem bidimensionalem Array vorliegen habe und nun wechselseitig den höchsten Initiativewert finden muss, dann aus dem anderen Array ein zufälliges Opfer auswählen muss, welches noch über Lebenspunkte > 0 verfügen muss.

Armee A: nach höchstem Initiativewert vorsortiertes bidim. Array
Armee B: nach höchstem Initiativewert vorsortiertes bidim. Array

Angedachter Programverlauf:
-ermittel den Krieger mit der höchsten Initiative aus beiden Armeen
-suche ein Opfer aus der anderen Armee mit Lebensenergie > 0
-individueller Kampf
-wiederhole, bis in einer Armee kein Element mit Lebensenergie >0 mehr vorhanden ist.

Ein konkreter Tipp wie ich das am besten im PHP-Code realisieren könnte, würde mich sicher schon ein ganzes Stück weiterbringen. Vielleicht fehlt mir nur die richtige Idee.

Danke, Sandra :)
 
Ok, probieren wir es mal.
Original geschrieben von Sandra Haupt
-ermittel den Krieger mit der höchsten Initiative aus beiden Armeen
Ich würde mir hierzu eine Funktion ermitteln, die das Array durchläuft und bei jeden Krieger diesen von dir gewünschten Wert checkt und wenn er höher als der bisher höchste ist, ersetzt.
PHP:
function getSoldierWithHighestInitiative($armeeArray) {
  $highestSolider['ID'] = "";
  $highestSolider['Initiative'] = "";
  foreach($armeeArray as $v) {
    if($v['Initiative'] > $highesSoldier['Initiative']){
      $highestSoldier['ID'] = $v['ID'];
      $highestSoldier['Initiative'] = $v['Initiative'];
    }
  }
  return $highestSoldier;
}
Alles natürlich rein theoretisch, da ich ja über den genauen Aufbau deiner Arrays nichts weiss. Aber ich denke das sollte als Ansatz reichen.

-suche ein Opfer aus der anderen Armee mit Lebensenergie > 0
PHP:
function getEnemyFrom($armeeArray){
  foreach($armeeArray as $v){
    if($v['lebensenergie'] > 0){
      $tempArray[] = $v;
    }
  }
  return $tempArray[array_rand($tempArray)];
}
[phpf]array_rand[/phpf]


-individueller Kampf
-wiederhole, bis in einer Armee kein Element mit Lebensenergie >0 mehr vorhanden ist.
Spontan keine Ahnung, sollte aber auch kein Problem sein.
 
Vielen Dank Tim,

das hilft mir in der Tat erheblich weiter, vor allem Deine Funktion get EnemyFrom().

In der Funktion getSoldierWithHighestInitiative($armeeArray) muss ich noch irgendwie kontrollieren, ob der ermittelte Soldat mit der höchsten Initiative bereits seinen Angriff ausgeführt hat in dieser Kampfrunde. Mit dem Index einer Schleife komme ich nicht richtig weiter, weil ich das Array zwischendurch sicher immer wieder resetten muss. Ich denke, ich muss bei jedem Funktionsaufruf zwischenspeichern, dass der aktuelle Soldat seinen Angriff nun ausgeführt hat und für die zukünftigen Angriffe dieser Runde nicht mehr zur Verfügung steht . Fällt Dir dazu spontan noch ein Lösungsvorschlag ein?
 
Ausgehend von dem Gedanken, dass deine Armee ein mehrdimensionales Array ist, das wie folgt aufgebaut ist
Code:
Array
  Soldat 1
    Eigenschaft 1
    Eigenschaft 2
    Eigenschaft 3
  Soldat 2
    Eigenschaft 1
    Eigenschaft 2
    ...
  ...
Dann greifst du ja via $array[0]['eigenschaft1'] auf die erste Eigenschaft des ersten Soldaten zu. Hier kannst meiner Meinung nach einfach eine weitere "Eigenschaft" mit namen bereits gekämpft einführen, die du abfragen und bei Bedarf neu setzen kannst.
 
OK, so versuche ich es einmal. Ich schreibe dann später den Erfolg / Misserfolg hier dazu. Bestimmt tauchen noch weitere für mich "unlösbare" Probleme auf. :)

Vielen Dank, Sandra
 
Zurück