Zum Inhalt springen

MidWar [Midgard Kampfsimulator]


Mav3N

Empfohlene Beiträge

Geschrieben

So, ich arbeite jetzt an Version 2.0 mit einem Positionssystem und dem implementiertem A* Algorithmus zur automatisierten Wegfindung. Das ganze wird ein wenig dauern. Bitte habt Geduld.

 

Bamba

  • 2 Wochen später...
Geschrieben

Nachtrag kritische Ereignisse (ich denke du hast das schon auf der Liste)

gewürfelt 20 ist immer ein Erfolg, gewürfelt 1 immer ein Misserfolg.

In einem Beispiel in dem Kämpfer 1 mit EW 0 und 500 LP nur bei kritischen Treffer erfolgreich sein kann (dann aber tödlich ist) gegen Kämpfer 2 der immer trifft (EW 19) aber nur 1 Schadenspunkt anrichtet entscheiden die AP von Kämpfer 1 ob er gewinnt (1000 AP) oder verliert (1 AP). Das dürfte nicht sein, da Kämpfer 1 genügend kritische Treffer landen sollte, dass er den Kampf immer gewinnt. Wenn Kämpfer 2 keinen Schaden anrichten kann, lässt sich der Kampf nicht mehr berechnen wenn Kämpfer 1 keine AP hat. Auch da müsste Kämpfer 1 per kritischem Erfolg den Kampf innert nützlicher Frist immer gewinnen.

es grüsst

Sayah el Atir al Azif ibn Mullah

Geschrieben

Hmmm. Dann hab ich vielleicht wieder einmal die Regeln falsch im Kopf. Ich dachte gewürfelte 20 sei kritischer Erfolg, egal was auch immer. Hat jemand ein Regelwerk zu Hand und kann schnell :read: ? Wie ist es umgekehrt? gewürfelt 1 bei EW +19 müsste trotz der erreichten 20 ein kritischer Fehler sein, richtig?

es grüsst

Sayah el Atir al Azif ibn Mullah

Geschrieben (bearbeitet)
Wie ist es umgekehrt? gewürfelt 1 bei EW +19 müsste trotz der erreichten 20 ein kritischer Fehler sein, richtig?

es grüsst

Sayah el Atir al Azif ibn Mullah

 

Richtig ;)

 

Vielleicht habe auch ich mich vertan (finde die Stelle grad selber nicht) ;)

Bearbeitet von KageMurai
Geschrieben

Du meinst vermutlich folgenden Sachverhalt: Sind die Abzüge höher als der Erfolgswert, glückt der EW:Angriff bei einer gewürfelten 20 dennoch, richtet aber nur kritischen Schaden an, wenn der WW:Abwehr misslingt, ansonsten normalen schweren Schaden (DFR S. 242).

 

Gruß

Pandike

Geschrieben
Du meinst vermutlich folgenden Sachverhalt: Sind die Abzüge höher als der Erfolgswert, glückt der EW:Angriff bei einer gewürfelten 20 dennoch, richtet aber nur kritischen Schaden an, wenn der WW:Abwehr misslingt, ansonsten normalen schweren Schaden (DFR S. 242).

 

Gruß

Pandike

 

Das kann sein :lol: (ist jedoch leider nicht auf einen EW von +0 anwendbar)

Danke Pandike :thumbs:

Geschrieben
Du meinst vermutlich folgenden Sachverhalt: Sind die Abzüge höher als der Erfolgswert, glückt der EW:Angriff bei einer gewürfelten 20 dennoch, richtet aber nur kritischen Schaden an, wenn der WW:Abwehr misslingt, ansonsten normalen schweren Schaden (DFR S. 242).

 

Gruß

Pandike

Ah so, danke. Wieder etwas gelernt.

es grüsst

Sayah el Atir al Azif ibn Mullah

  • 2 Monate später...
Geschrieben

Hallo,

 

ich hatte die letzten Wochen mit meinem Umzug nach Köln zutun und bin nicht zuviel gekommen. Da das ganze jetzt aber abgeschlossen ist, hatte ich Zeit mich die letzten Tage mal ausführlich mit dem A*-Algorithmus auseinander zusetzen.

 

Ich habe es jetzt geschafft den A*-Algorithmus in PHP zu implementieren, was bedeutet, dass die automatisierte Wegfindung (Welche Optimal ist (Existiert ein Weg, wird er gefunden) - das ist mathematisch bewiesen) bereits funktioniert. Wenn ich mein astar.php also nun mit dem bisherigen Kampfsimulator zusammenschmeiße, kämpfen die Figuren nach den bisher umgesetzten Regeln und bewegen sich gleichzeitig realistisch auf einem Schachbrett.

 

Hört sich erstmal gut an, oder?

 

Bevor ich das zusammenfüge, werde ich aber meine astar.php erstmal ausführlich auf Fehler aller Art testen - schließlich bin ich nur Hobbyprogrammierer und bei mir kommt es öfter mal vor, dass sich ein Fehler einschleicht. Ich poste den PHP Quellcode hier einfach mal, da es hier einige gibt, die sich damit auskennen (Solwac war das glaube ich) und vllt. mit nach Fehlern suchen können. Erst wenn wir uns alle sicher sind, dass meine astar.php Fehlerfrei ist, füge ich sie mit dem bisherigen Kampfsimulator zusammen.

 

Bamba

 

Quellcode von astar.php:

(Bitte bedenkt, dass das ganze noch nicht ausgereift ist, ich werde noch 'ne Menge ändern. Professionelle Programmierer würden von einer Beta-Version sprechen) :D

 

<?php

error_reporting(E_ALL);

class astar {
 private $x;
 private $y;
 private $openlist = array();
 private $closedlist = array();
 private $tx;
 private $ty;

 public function __construct($x,$y) {
   // Zu übergebende Werte: $x = Anzahl Felder auf der X-Achse,
   // $y = Anzahl Felder auf der Y-Achse, Hindernisse
   // WICHTIG: IRGENDWIE NOCH DIE HINDERNISSE IN DIE CONSTRUCT FUNC EINBAUEN
   $this->x = $x;
   $this->y = $y;      
   // Hier Hindernisse manuell einfügen, solange das noch nicht über die Construct Funktion geregelt wird
   array_push($this->closedlist,array("X" => 1, "Y" => 2));
   array_push($this->closedlist,array("X" => 1, "Y" => 3));
   array_push($this->closedlist,array("X" => 2, "Y" => 2));
   array_push($this->closedlist,array("X" => 3, "Y" => 2));
 }
 public function main($x,$y,$tx,$ty) {
   // Berechnet den Weg vom Start zum Zielnode
   // X = X-Koordinate, Y = Y-Koordinate
   // G = Bisherige Wegkosten
   // C = Kosten Vorgängernode -> currentNode
   // H = Geschätzte Restkosten (Luftlinien Heuristik)
   // F = Gesamtkosten

   // Vorbelegungen
   $Start = array();
   $Start["X"] = $x; $Start["Y"] = $y; $Start["G"] = 0; $Start["VX"] = -1;  $Start["VY"] = -1;
   $this->tx = $tx; $this->ty = $ty;

   // Ganz zu Anfang des Skriptes den Startnode in die Openlist einfügen
   array_push($this->openlist,$Start);

   do {
     // Die Openlist nach dem niedrigstem F-Wert sortieren
     usort($this->openlist,'Compare');

     // Wenn der Aktuelle Node gleich dem Zielnode ist -> Weg gefunden
     $ActualNode = array("X" => $this->openlist[0]["X"],"Y" => $this->openlist[0]["Y"],"VX" => $this->openlist[0]["VX"],"VY" => $this->openlist[0]["VY"]);
     if($ActualNode["X"] == $this->tx && $ActualNode["Y"] == $this->ty) {
       array_push($this->closedlist,$ActualNode);
       $this->getWay();
       die("PATHFOUND");
     }
     else {
       // Wenn nicht, wird vom Punkt mit dem niedrigstem F-Wert weitergesucht
       $this->expandNode($ActualNode["X"],$ActualNode["Y"]);
       // Den fertig untersuchen Node auf die Closedlist setzen und aus der Openlist löschen
       array_push($this->closedlist,$ActualNode);
       unset($this->openlist[0]);
     }
   }
   // Bis die Openlist leer ist
   while(!empty($this->openlist));
   // Ist die Openlist leer und es wurde nicht abgebrochen, existiert kein Weg
   die("ES GIBT KEINEN WEG");
 }
 private function expandNode($x,$y) {
   // Expandiert den Node
   $i=0;
   $Successor = array();
   $Successors = $this->getSuccessors($x,$y);

   foreach($Successors as $Index => $Current) {
     // Geht jeden Nachfolgenode einzeln durch 
     array_push($Successor,$Current);

     if($i%2 != 0) {
       // Tritt nur jedes zweite mal in Kraft da immer erst BEIDE 
       // Werte (X und Y Koordinate) $Successor hinzugefügt werden müssen
       // Überprüft, ob $Successor in der Closedlist ist
       $Inside = $this->inClosedList($Successor);
       if($Inside == TRUE) {
         // Wenn $Successor innerhalb der Closedlist ist, mache nichts  außer $Successor zu leeren
         $Successor = array();
         $i++;
         continue;
       }
       else {
         // F Wert von $Successor berechnen
         $g = 0;
         foreach($this->openlist as $Key) {
           // Holt den G Wert vom aktuellen Node
           if($x == $Key["X"] && $y == $Key["Y"]) {
             $g = $Key["G"];
             break;
           }
         }
         switch($Index) {
           // Berechnet den C Wert zwischen aktuellem Node und Successor
           case "ol_y": 
             $c = sqrt(2);
             break;
           case "om_y": 
             $c = 1;
             break;
           case "or_y": 
             $c = sqrt(2);
             break;
           case "ml_y": 
             $c = 1;
             break;
           case "mr_y": 
             $c = 1;
             break;
           case "ul_y": 
             $c = sqrt(2);
             break;
           case "um_y": 
             $c = 1;
             break;
           case "ur_y": 
             $c = sqrt(2);
             break;
         }
         // Berechnet H Wert des Successors
         $XDifference = $Successor[0] - $this->tx;
         if($XDifference < 0) {
           $XDifference *= -1;
         }
         $YDifference = $Successor[1] - $this->ty;
         if($YDifference < 0) {
           $YDifference *= -1;
         }
         $h = sqrt($XDifference * $XDifference + $YDifference * $YDifference);
         // G, C und H Wert werden zum F Wert addiert
         $f = $g + $c + $h;

         $Exit = FALSE;
         for($n=0;$n<count($this->openlist);$n++) {
           if($Successor[0] == $this->openlist[$n]["X"] && $Successor[1] == $this->openlist[$n]["Y"]) {
             if($f > $this->openlist[$n]["F"]) {
               // Wenn Successor in der Openlist ist und der neue F Wert größer als 
               // der alte F Wert ist, tue nichts
               $Exit = TRUE;  
             }
             else {
               // Wenn Successor in der Openlist ist und der neue F Wert nicht größer als der
               // alte ist, den F Wert in der Openlist aktualisieren
               $this->openlist[$n]["F"] = $f;
               $Exit = TRUE;
             }
             break;
           }
         }
         if($Exit) {
           // Wenn der Successor bereits in der Openlist war und der F Wert falls nötig
           // aktualisiert wurde, $Successor leeren, $i inkrementieren und den Rest
           // des Schleifendurclaufes überspringen
           $Successor = array();
           $i++;
           continue;                                                      
         }
         // War der Successor garnicht in der Openlist, füge ihn hinzu
         $NewNode = array("X" => $Successor[0],"Y" => $Successor[1],"F" => $f,"G" => ($g + $c),"VX" => $x,"VY" => $y);
         array_push($this->openlist,$NewNode);
       }

       // $Successor leeren, damit sich keine Werte überschneiden
       $Successor = array();
     }
     $i++;
   }
 }  
 private function getSuccessors($x,$y) {
   // Bestimmt alle Umgebungsnodes von $x,$y

   $Successors = array();
   if(($x - 1 >= 0) && ($y + 1 <= $this->y)) {
     $Successors["ol_x"] = $x - 1; $Successors["ol_y"] = $y + 1;
   }
   if($y + 1 <= $this->y) {
     $Successors["om_x"] = $x; $Successors["om_y"] = $y + 1;
   }
   if(($x + 1 <= $this->x) && ($y + 1 <= $this->y)) {
     $Successors["or_x"] = $x + 1; $Successors["or_y"] = $y + 1;
   }
   if($x - 1 >= 0) {
     $Successors["ml_x"] = $x - 1; $Successors["ml_y"] = $y;
   }
   if($x + 1 <= $this->x) {
     $Successors["mr_x"] = $x + 1; $Successors["mr_y"] = $y;
   }
   if(($x - 1 >= 0) && ($y - 1 >= 0)) {
     $Successors["ul_x"] = $x - 1; $Successors["ul_y"] = $y - 1;
   }
   if($y - 1 >= 0) {
     $Successors["um_x"] = $x; $Successors["um_y"] = $y - 1;
   }
   if(($x + 1 <= $this->x) && ($y - 1 >= 0)) {
     $Successors["ur_x"] = $x + 1; $Successors["ur_y"] = $y - 1;
   }

   return $Successors;
 }
 private function inClosedlist($Successor) {
   // Überprüft, ob $Successor in der Closedlist vertreten ist
   $Inside = FALSE;
   for($j=0;$j<count($this->closedlist);$j++) {
     if($Successor[0] == $this->closedlist[$j]["X"] && $Successor[1] == $this->closedlist[$j]["Y"]) {
       $Inside = TRUE;
     }
   }
   return $Inside;
 }
 private function getWay() {
   // Berechnet aus $Closedlist den wirklichen Weg
   $Way = array();
   array_push($Way,end($this->closedlist));
   $Last = end($Way);
   do {
     foreach($this->closedlist as $Key) {
       if($Key["X"] == $Last["VX"] && $Key["Y"] == $Last["VY"]) {
         array_push($Way,$Key);
         break;
       }
     }
     $Last = end($Way);
   }
   while($Last["VX"] != -1 && $Last["VY"] != -1);
   $Way = array_reverse($Way);
   for($i=0;$i<count($Way);$i++) {
     echo "Feld $i: " . $Way[$i]["X"] . "," . $Way[$i]["Y"] . "<br>";
   }
   return $Way;
 }
}        

function Compare($first, $second) { 
       if($first['F'] < $second['F']) 
               return -1; 
       else if($first['F'] > $second['F']) 
               return 1; 
       else 
               return 0; 
}  
$map = new astar(4,9);
$map->main(1,0,2,3)

?>

  • Like 1
Geschrieben

Ich kenne PHP leider überhaupt nicht und kann auch sonst nicht programmieren, bin hier also keine Hilfe.

Deshalb: Danke für deine Bemühungen und viel Erfolg!:thumbs:

es grüsst

Sayah el Atir al Azif ibn Mullah

Geschrieben

Bevor ich das zusammenfüge, werde ich aber meine astar.php erstmal ausführlich auf Fehler aller Art testen - schließlich bin ich nur Hobbyprogrammierer und bei mir kommt es öfter mal vor, dass sich ein Fehler einschleicht. Ich poste den PHP Quellcode hier einfach mal, da es hier einige gibt, die sich damit auskennen (Solwac war das glaube ich) und vllt. mit nach Fehlern suchen können. Erst wenn wir uns alle sicher sind, dass meine astar.php Fehlerfrei ist, füge ich sie mit dem bisherigen Kampfsimulator zusammen.

Von mir erst mal ein paar kurze Anmerkungen... (Ist das die Portierung einer C-Version des Algorithmus? ;))

 

Die Methode inClosedList() durchsucht manuell das Array. Einer der wenigen Gründe, in PHP zu programmieren, ist der Wust von Array-Such- und Manipulationsfunktionen. Nimm lieber die, die sollten auch deutlich besser performen, wenn man nicht gerade einen Bytecodecompiler installiert hat. :D

 

Natürlich muss dann die Datenstruktur ein wenig angepasst werden. :schweiss:

Dazu passend der Konstruktor... besser wäre eine eigene Klasse, die das Spielfeld behandelt, dann kann man da auch über setter drauf zugreifen und muss dieses Gefummel mit array_push nicht weiter verfolgen.

 

Ausserdem kann man dann auch gleich durch Anpassung der Spielfeldklasse das Problem mit den Kontrollbereichen erschlagen...

:rueckzug:

 

Nein, ernsthaft: Strikt OOP-technisch kommst Du mit einer einzelnen Klasse wohl nicht aus.

Geschrieben

Bevor ich das zusammenfüge, werde ich aber meine astar.php erstmal ausführlich auf Fehler aller Art testen - schließlich bin ich nur Hobbyprogrammierer und bei mir kommt es öfter mal vor, dass sich ein Fehler einschleicht. Ich poste den PHP Quellcode hier einfach mal, da es hier einige gibt, die sich damit auskennen (Solwac war das glaube ich) und vllt. mit nach Fehlern suchen können. Erst wenn wir uns alle sicher sind, dass meine astar.php Fehlerfrei ist, füge ich sie mit dem bisherigen Kampfsimulator zusammen.

Von mir erst mal ein paar kurze Anmerkungen... (Ist das die Portierung einer C-Version des Algorithmus? ;))

 

Die Methode inClosedList() durchsucht manuell das Array. Einer der wenigen Gründe, in PHP zu programmieren, ist der Wust von Array-Such- und Manipulationsfunktionen. Nimm lieber die, die sollten auch deutlich besser performen, wenn man nicht gerade einen Bytecodecompiler installiert hat. :D

 

Natürlich muss dann die Datenstruktur ein wenig angepasst werden. :schweiss:

Dazu passend der Konstruktor... besser wäre eine eigene Klasse, die das Spielfeld behandelt, dann kann man da auch über setter drauf zugreifen und muss dieses Gefummel mit array_push nicht weiter verfolgen.

 

Ausserdem kann man dann auch gleich durch Anpassung der Spielfeldklasse das Problem mit den Kontrollbereichen erschlagen...

:rueckzug:

 

Nein, ernsthaft: Strikt OOP-technisch kommst Du mit einer einzelnen Klasse wohl nicht aus.

 

Hi,

 

NEIN das ist keine Portierung einer C-Version, ich habe mir http://de.wikipedia.org/wiki/A*-Algorithmus genommen und das ganze in 2 Tagen frei runter programmiert. Funktioniert soweit ich das sehe relativ gut, ich will bloß sicher sein, dass es eine 100% Implementierung ist (An der Funktionstüchtigkeit nicht an der Geschwindigkeit gemessen).

 

Vielen Dank für deine Anregungen, ich werde mal schauen was ich da noch drehen kann... :D Aber ich bin halt ein Hobbyprogrammierer und sonst nichts. :P

Geschrieben

So, ich habe mich mal durch das PHP durchgekämpft. :schweiss:

 

Ich empfinde es nicht als gut lesbar. Es wäre wirklich sinnvoll, weitere Klassen zu verwenden und einige Funktionen zu kapseln. Als Kandidaten sehe ich Punkte (x,y), Graphen (um die möglichen Wege mit Backtracking abzuschreiten) und das Spielfeld (dabei können dann Hindernisse, Kontrollbereiche usw. erschlagen werden).

 

Die eigentliche Implementation scheint mir aber korrekt zu sein. Zumindest ist die Heuristic-Funktion brauchbar und erfüllt alle Bedingungen. h ist monoton und somit sollte immer ein Optimum gefunden werden.

 

Warum verwendest Du A*? Ich habe nicht die Erfahrung mit umfangreichen Rechenaufgaben in PHP, aber ich stelle mir den Speicheraufwand bei größeren Feldern als nicht zu unterschätzenden Nachteil vor. Außerdem findet der Algorithmus nur einen kürzesten Weg. Für eine Kampfsimulation könnte es sinnvoller sein, wenn alle möglichsten kürzesten Wege ermittelt werden um dann für mehrere Figuren das Optimum zu finden. Bellman-Ford wäre dann eine Alternative.

 

Sollte die Laufzeit irgendwann beim Einsatz zu sehr anwachsen, dann wäre D* vielleicht besser. Das habe ich aber noch nie programmiert. :lookaround:

 

Solwac

Geschrieben
So, ich habe mich mal durch das PHP durchgekämpft. :schweiss:

 

Ich empfinde es nicht als gut lesbar. Es wäre wirklich sinnvoll, weitere Klassen zu verwenden und einige Funktionen zu kapseln. Als Kandidaten sehe ich Punkte (x,y), Graphen (um die möglichen Wege mit Backtracking abzuschreiten) und das Spielfeld (dabei können dann Hindernisse, Kontrollbereiche usw. erschlagen werden).

 

Ich mal gerade den anderen Quellcode des Kampfsimulators angeguckt und mir überlegt wie man das ganze aufteilen könnte. Das heißt ich werde das ganze jetzt in kleinere Klassen aufteilen und besser verteilen.

 

Die eigentliche Implementation scheint mir aber korrekt zu sein. Zumindest ist die Heuristic-Funktion brauchbar und erfüllt alle Bedingungen. h ist monoton und somit sollte immer ein Optimum gefunden werden.

 

Dachte ich auch, aber starte mal mein Skript mit:

 

$map = new astar(4,9);
$map->main(4,0,0,2)

 

und den Hindernissen:

 

array_push($this->closedlist,array("X" => 1, "Y" => 2));
   array_push($this->closedlist,array("X" => 1, "Y" => 3));
   array_push($this->closedlist,array("X" => 2, "Y" => 2));
   array_push($this->closedlist,array("X" => 3, "Y" => 2));
   array_push($this->closedlist,array("X" => 2, "Y" => 0));
   array_push($this->closedlist,array("X" => 2, "Y" => 1));

 

Normalerweise sollte er um diese Mauer rumgehen, allerdings läuft er direkt am Anfang einmal Zickzack, nämlich:

 

Feld 0: 4,0

Feld 1: 3,1

Feld 2: 4,2

Feld 3: 3,3

Feld 4: 2,3

Feld 5: 1,4

Feld 6: 0,3

Feld 7: 0,2

 

(Debug Output von meinem astar.php). Schau dir die ersten 3 Felder an. Wäre er optimal müsste es doch 4,0 - 4,1 - 4,2 heißen und nicht 3,1. Kann mir das jemand erklären? :worried:

 

Warum verwendest Du A*? Ich habe nicht die Erfahrung mit umfangreichen Rechenaufgaben in PHP, aber ich stelle mir den Speicheraufwand bei größeren Feldern als nicht zu unterschätzenden Nachteil vor. Außerdem findet der Algorithmus nur einen kürzesten Weg. Für eine Kampfsimulation könnte es sinnvoller sein, wenn alle möglichsten kürzesten Wege ermittelt werden um dann für mehrere Figuren das Optimum zu finden. Bellman-Ford wäre dann eine Alternative.

 

Ich verwende A*, weil es ganz einfach derjenige war, den ich kannte. Eine zeitlang hab ich sogar einen eigenen Algorithmus hierfür entwickelt das ganze dann aber wieder verworfen. Ich denke das ist der bekannteste Algorithmus für soetwas und dann war es halt Zufall, dass ich ihn benutzt habe. Speicheraufwand? Hm, ja, das wird ein Problem aber ich glaube kaum, dass wir in Feldern mit 10.000 x 20.000 kämpfen werden. Also dürfte das noch machbar sein, wenn ich mir zum Debug die Openlist ausgeben lasse, ist sie bei 4 x 9 auch nicht so arg groß und bei 20x100, ist es auch noch überschaubar.

 

Er findet nur einen kürzesten Weg? Na das macht doch nichts. Wie oben erwähnt werde ich das ganze in mehrere Klassen aufteilen die oberste Klasse wird dann die feindliche Kämpferliste durchgehen und für jeden den Weg berechnen von aktuelle Spielerfigur -> Feind, so dass ich eine Liste mit möglichen Wegen erhalten, deren kürzesten ich einfach nehme. So dürfte ja jeder Kämpfer in Echt in einer Schlacht auch denken. Problem gelöst. :P

 

Sollte die Laufzeit irgendwann beim Einsatz zu sehr anwachsen, dann wäre D* vielleicht besser. Das habe ich aber noch nie programmiert. :lookaround:

 

Solwac

 

D* ist nicht optimal und wenn ich eines hasse, dann unzählige Exeptions festzulegen. Daher werde ich nicht auf D* ausweichen. Er ist nur suboptimal. Will heißen ich bleibe bei meinem derzeitigen Astar, werde das ganze noch in mehrere Klassen zwecks Übersichtlichkeit und Handling aufteilen und dann mit meinem bisherigen Simulator verschmelzen.

 

Die Methode inClosedList() durchsucht manuell das Array. Einer der wenigen Gründe, in PHP zu programmieren, ist der Wust von Array-Such- und Manipulationsfunktionen. Nimm lieber die, die sollten auch deutlich besser performen, wenn man nicht gerade einen Bytecodecompiler installiert hat. :D

 

Natürlich muss dann die Datenstruktur ein wenig angepasst werden. :schweiss:

 

Nun, ich habe mir diesen Aufbau der Openlist und der Closedlist aus mehreren Gründen so überlegt. Und ich habe eigentlich keine Lust das ganze Script umzubasteln, nur um dann eine kleine derartige Funktion inClosedlist() einzusparen und eine PHP-Standardfunktion verwenden zu können. Daher belasse ich es dabei. Es hätte bessere Wege gegeben aber was solls. Ich bin schließlich kein Profi.

 

Dazu passend der Konstruktor... besser wäre eine eigene Klasse, die das Spielfeld behandelt, dann kann man da auch über setter drauf zugreifen und muss dieses Gefummel mit array_push nicht weiter verfolgen.

 

Ausserdem kann man dann auch gleich durch Anpassung der Spielfeldklasse das Problem mit den Kontrollbereichen erschlagen...

 

Wie oben erwähnt: Ich teile das ganze in mehrere Klassen auf und dann hat sich die Sache.

 

Ich mache dann jetzt sofort weiter, nur kann mir bitte einer erklären was mit der Situation da oben ist, die nur suboptimal rechnet und warum und wie man das behebt? Kann ja sein, dass ich mich da gerade irre, aber ich glaube irgendwo müsste mir ein Fehler unterlaufen sein, sonst dürfte er einen derartigen Zickzackkurs nicht ausrechnen. Solwac schau doch noch mal. :D

 

Bamba, der vorhat sämtliche M4 Regeln umzusetzen :uhoh:

Geschrieben
(Debug Output von meinem astar.php). Schau dir die ersten 3 Felder an. Wäre er optimal müsste es doch 4,0 - 4,1 - 4,2 heißen und nicht 3,1. Kann mir das jemand erklären? :worried:
Du solltest die Ausgabe im Debugmodus etwas mehr erzählen lassen. Wie lang ist der Weg laut Programm und wie lang sind die Alternativen?

 

Ergänzend wäre eine Ausgabe von Open und Closed List mit den Werten für f und h.

 

Solwac

Geschrieben
(Debug Output von meinem astar.php). Schau dir die ersten 3 Felder an. Wäre er optimal müsste es doch 4,0 - 4,1 - 4,2 heißen und nicht 3,1. Kann mir das jemand erklären? :worried:
Du solltest die Ausgabe im Debugmodus etwas mehr erzählen lassen. Wie lang ist der Weg laut Programm und wie lang sind die Alternativen?

 

Ergänzend wäre eine Ausgabe von Open und Closed List mit den Werten für f und h.

 

Solwac

 

Also wenn ich mir die closedlist in der getWay() Funktion ausgeben lasse, sieht das so aus:

 

array(19) { [0]=> array(2) { ["X"]=> int(1) ["Y"]=> int(2) } [1]=> array(2) { ["X"]=> int(1) ["Y"]=> int(3) } [2]=> array(2) { ["X"]=> int(2) ["Y"]=> int(2) } [3]=> array(2) { ["X"]=> int(3) ["Y"]=> int(2) } [4]=> array(2) { ["X"]=> int(2) ["Y"]=> int(0) } [5]=> array(2) { ["X"]=> int(2) ["Y"]=> int(1) } [6]=> array(4) { ["X"]=> int(4) ["Y"]=> int(0) ["VX"]=> int(-1) ["VY"]=> int(-1) } [7]=> array(4) { ["X"]=> int(3) ["Y"]=> int(1) ["VX"]=> int(4) ["VY"]=> int(0) } [8]=> array(4) { ["X"]=> int(3) ["Y"]=> int(0) ["VX"]=> int(4) ["VY"]=> int(0) } [9]=> array(4) { ["X"]=> int(4) ["Y"]=> int(1) ["VX"]=> int(4) ["VY"]=> int(0) } [10]=> array(4) { ["X"]=> int(4) ["Y"]=> int(2) ["VX"]=> int(3) ["VY"]=> int(1) } [11]=> array(4) { ["X"]=> int(3) ["Y"]=> int(3) ["VX"]=> int(4) ["VY"]=> int(2) } [12]=> array(4) { ["X"]=> int(2) ["Y"]=> int(3) ["VX"]=> int(3) ["VY"]=> int(3) } [13]=> array(4) { ["X"]=> int(4) ["Y"]=> int(3) ["VX"]=> int(4) ["VY"]=> int(2) } [14]=> array(4) { ["X"]=> int(2) ["Y"]=> int(4) ["VX"]=> int(3) ["VY"]=> int(3) } [15]=> array(4) { ["X"]=> int(3) ["Y"]=> int(4) ["VX"]=> int(3) ["VY"]=> int(3) } [16]=> array(4) { ["X"]=> int(1) ["Y"]=> int(4) ["VX"]=> int(2) ["VY"]=> int(3) } [17]=> array(4) { ["X"]=> int(0) ["Y"]=> int(3) ["VX"]=> int(1) ["VY"]=> int(4) } [18]=> array(4) { ["X"]=> int(0) ["Y"]=> int(2) ["VX"]=> int(0) ["VY"]=> int(3) } }

 

Und die Openlist:

 

array(8) { [0]=> array(6) { ["X"]=> int(0) ["Y"]=> int(2) ["F"]=> float(9.0710678118655) ["G"]=> float(9.0710678118655) ["VX"]=> int(0) ["VY"]=> int(3) } [1]=> array(6) { ["X"]=> int(4) ["Y"]=> int(4) ["F"]=> float(9.3005630797458) ["G"]=> float(5.6568542494924) ["VX"]=> int(3) ["VY"]=> int(3) } [2]=> array(6) { ["X"]=> int(0) ["Y"]=> int(4) ["F"]=> float(9.6568542494924) ["G"]=> float(7.6568542494924) ["VX"]=> int(1) ["VY"]=> int(4) } [3]=> array(6) { ["X"]=> int(1) ["Y"]=> int(5) ["F"]=> float(10.233345472034) ["G"]=> float(7.0710678118655) ["VX"]=> int(2) ["VY"]=> int(4) } [4]=> array(6) { ["X"]=> int(2) ["Y"]=> int(5) ["F"]=> float(10.262405524956) ["G"]=> float(6.6568542494924) ["VX"]=> int(2) ["VY"]=> int(4) } [5]=> array(6) { ["X"]=> int(3) ["Y"]=> int(5) ["F"]=> float(10.485281374239) ["G"]=> float(7.0710678118655) ["VX"]=> int(2) ["VY"]=> int(4) } [6]=> array(6) { ["X"]=> int(0) ["Y"]=> int(5) ["F"]=> float(11.071067811865) ["G"]=> float(8.0710678118655) ["VX"]=> int(1) ["VY"]=> int(4) } [7]=> array(6) { ["X"]=> int(4) ["Y"]=> int(5) ["F"]=> float(11.656854249492) ["G"]=> float(6.6568542494924) ["VX"]=> int(3) ["VY"]=> int(4) } }

 

Zur Erklärung: Die jenigen in der Closedlist, die nur 2 Einträge besitzen nämlich X und Y sind die Hindernisse die anderen sind die Felder die möglicherweise begangen werden könnten. Hier steht mit VX und VY jeweils der Vorgänger mit den X und Y Koordinaten. Ich fange einfach beim Ziel an und verfolge die Liste zurück, bis ich beim Start bin und habe den Weg.

 

Hier nochmal das ganze für dich aufgemalt:

 

http://www.5load.de/img_67932_koh.gif

 

Und irgendwie kann das einfach nicht sein - wo mache ich den Fehler, denn das ist wirklich nur suboptimal.

 

Bamba

Geschrieben

Es gab wirklich einen Fehler in meiner astar.php, bei dem ich vergaß Vorgängerknoten zu aktualisieren. Das Problem ist nun dank Hilfe eines sehr erfahrenen Programmierers gelöst. Astar funktioniert, ich werde es nun mit der restlichen Codebibliothek zusammenfügen - bald können unsere Kämpfer auch auf Karten laufen. :D

Geschrieben

So, hab jetzt endlich Version 2.0 fertig. Größte Veränderung ist natürlich die Möglichkeit, dass sich Spielerfiguren wie auf einem Schachbrett bewegen können und sich Wege anhand des A* Algorithmus suchen. Ich lade derzeit alle Daten von piranho auf Lima-city.de - der Server ist besser.

 

http://midwar.lima-city.de/V2.0/insert.php

 

Das ist erstmal gerade die Adresse. Folgende Features unterstützt der Simulator nun:

 

- Angreifen
- Abwehren 
- Abwehren nicht erlaubt wenn Verteidiger 0 AP hat
- Schadenkalkulation
- Kampfunfähig ab 3 LP
- Rüstung
- Nicht unter 0 AP erlaubt
- Minus 2 auf Angriffe wenn Angreifer LP/2 hat
- Minus 4 auf Angriffe wenn Angreifer 0 AP hat
- Plus 4 auf Angriff, wenn Verteidiger 0 AP hat
- Anzeige wer gestorben / Kampfunfähig ist
- Namensgebung möglich
- Zufällige Gegnerwahl
- Kampfinformationen ausschaltbar
- Rundenanzeige
- Statistikkampf
- Inputüberprüfung
- Standardbelegungen für Kämpfer
- Rundenkampf
- Kämpfer können sich bewegen, suchen selbstständig Wege zum Ziel
- Bewegungsweite
- -6 auf EW:Angriff, wenn diese Runde mehr als die Hälfte der Bewegungsweite verbraucht wurde
- -2 auf den EW:Verteidigung, wenn diese Runde mehr als die Hälfte der Bewegungsweite verbraucht wurde
- Positionsanzeige

 

ACHTUNG: Es gibt in dieser Version, weil sich intern im Quellcode immens viel geändert hat, noch einige Probleme.

 

1. Die Eingaben für die X,Y und B Werte in insert.php werden noch nicht überprüft! Hierüber sind derzeit noch Attacken möglich (Ich glaube aber mal nicht, dass sich ein Midgard-Spieler dazu durchringt ;)) Bitte achtet darauf, dass ihr vernünftige Werte eingebt.

2. Die Gegnerauswahl ist derzeit IMMER NOCH per Zufall, erst in der nächsten Version werde ich hinzufügen, dass er sie sich anhand des Kriteriums der Entfernung aussucht. Trotz alledem suchen sich die Spieler nun den richtigen Weg auf dem Schachbrett, gehen ihn und greifen dann an.

 

Und ganz besonders wichtig: Derzeit lasse ich einen Spieler seine kompletten Aktionen ausführen und erst dann den nächsten Spieler. Das muss ich noch ändern. Es soll am Ende so ablaufen, dass Spieler 1 einen Schritt geht, dann Spieler 2 einen Schritt seines Weges, etc. Schließlich soll das ganze ja möglichst dem Begriff der Gleichzeitigkeit nahekommen. Derzeit läuft ein Spieler leider erst seinen ganzen Weg, greift dann an, und dann ist der nächste dran. Da hab' ich noch eine Menge zutun.

 

Bitte fleißig Fehler suchen, ich vermute, dass eine ganze Menge drinnen sind, da ich so ziemlich die Hälfte des Simulators intern umschreiben musste.

 

Bamba (Ich schaff' das noch alle M4 Regeln umzusetzen!)

Geschrieben

Es hat sich ein Fehler bei der Schadensberechnung eingeschlichen: meine Kämpfer hatten Lederrüstungen, aber egal wieviel Schaden der Gegner anrichtet, es wurde immer 0LP Schaden verrechnet.

es grüsst

Sayah el Atir al Azif ibn Mullah

Geschrieben (bearbeitet)
Es hat sich ein Fehler bei der Schadensberechnung eingeschlichen: meine Kämpfer hatten Lederrüstungen, aber egal wieviel Schaden der Gegner anrichtet, es wurde immer 0LP Schaden verrechnet.

es grüsst

Sayah el Atir al Azif ibn Mullah

 

Ich weiß nicht, was du eingegeben hast, bei mir funktioniert das alles. :worried:

 

EDIT: Alle Fehler, die ihr findet bitte mit Screenshot hier posten!

Bearbeitet von Bamba
Geschrieben

Ich habe auf deinen Link geklickt. 3 Teams erstellt mit je einem Kämpfer:

Kampfinformationen:

�berlebende:

Name ID LP AP Schaden Team Angriffswert Verteidigungswert R�stung Status X Y B

Person_1 1 12 10 1W6 1 5 12 Lederr�stung Unbeeintr�chtigt 1 1 3

Person_2 2 12 10 1W6 2 5 12 Lederr�stung Unbeeintr�chtigt 9 9 4

Person_3 3 12 10 1W6 03 5 12 Lederr�stung Unbeeintr�chtigt 9 1 9

Runde: 1

Anzahl verschiedener Teams: 3

Person 1 sollte ein Oger ab drop down liste sein, wurde nicht übernommen.

"Person_1 mit der ID 1 geht 4 auf Feld 5,3, kann diese Runde aber nicht angreifen, da er diese Runde nicht gen�gend weit gehen konnte." macht keinen Sinn.

"Person_2 mit der ID 2 erzielt 24 und hat Person_1 mit der ID 1 getroffen. Person_1 mit der ID 1 erzielt 22, kann nicht abwehren, erh�lt 4 Schadenspunkte und verliert 0 LP und 4 AP."

Das ist ein schwerer Treffer, die Rüstung sollte LR sein also müssten 2 LP Schaden verrechnet werden.

da so natürlich niemand stirbt endet die Simulation irgendwann mit dem entsprechenden Fehler.

es grüsst

Sayah el Atir al Azif ibn Mullah

Geschrieben
1. Die Eingaben für die X,Y und B Werte in insert.php werden noch nicht überprüft! Hierüber sind derzeit noch Attacken möglich (Ich glaube aber mal nicht, dass sich ein Midgard-Spieler dazu durchringt ;)) Bitte achtet darauf, dass ihr vernünftige Werte eingebt.
Wobei X und Y die Startposition angeben (X=0, Y=0 entspricht links oben) und B die Bewegungsweite ist. Ist es Absicht, dass man für die drei Werte maximal eine einstellige Zahl eingeben kann?

 

Und ganz besonders wichtig: Derzeit lasse ich einen Spieler seine kompletten Aktionen ausführen und erst dann den nächsten Spieler. Das muss ich noch ändern. Es soll am Ende so ablaufen, dass Spieler 1 einen Schritt geht, dann Spieler 2 einen Schritt seines Weges, etc.
D.h. du willst zunächst die sekundengenauen Regeln zur Abwicklung einer Kampfrunde umsetzen? Wäre es nicht sinnvoll, erstmal die 10-Sekunden Runde zu implementieren?

 

Was mir noch aufgefallen: Es wäre schön, wenn man einstellen könnte, wie riskant ein Kämpfer kämpfen soll, d.h. ob er z.B. einen überstürzten Angriff macht oder nicht.

 

Screenshots für Fehler sind etwas schwierig, da man hier im Forum als normaler Nutzer keine Bilder anhängen kann. Vielleicht überlegst du dir noch einen Debug-Modus, der ein Text-Debuglog erzeug, das man dann hier posten kann.

 

CU

FLo

Geschrieben

Bin dabei die Fehler zu suchen, demnächst gibt es eine Fehlerbereinigte neue Version.

 

Ich hab an Elsa eine PN geschickt, in der ich sie darum bitte den Simulator, nachdem ich noch ein wenig Funktionen zur Sicherheit hinzugefügt habe, auf die offizielle Seite zu nehmen. Ich fände es gut, wenn sie sich hier dazu äußert, dann können alle mitdiskutieren.

 

Bamba

Erstelle ein Benutzerkonto oder melde Dich an, um zu kommentieren

Du musst ein Benutzerkonto haben, um einen Kommentar verfassen zu können

Benutzerkonto erstellen

Neues Benutzerkonto für unsere Community erstellen. Es ist einfach!

Neues Benutzerkonto erstellen

Anmelden

Du hast bereits ein Benutzerkonto? Melde Dich hier an.

Jetzt anmelden
×
×
  • Neu erstellen...