Seite 2 von 2 ErsteErste 12
Ergebnis 16 bis 23 von 23

Thema: Kampfwerteberechnung falsch

  1. #16
    hat den Blues Avatar von Elwood
    Registriert seit
    05.11.07
    Beiträge
    4.352
    Hei Commander ,

    schreibst du hier noch mal weiter? Ich habe das ganze versucht nachzuvollziehen, und bin mir nicht ganz sicher, was ich da im Endeffekt für Schlüsse daraus ziehen kann:

    Sind Veterean-Beförderungen "besser" als andere, weil sie wirklich der Einheit, die sie hat, direkt angerechnet werden?
    Was änderte das Unterschreiten der kleiner gleich 0 Grenze bei den Verteidigerboni effektiv, ist der Malus dann ncoh stärker?
    Geschichten zum Lesen ...

    Der seltsame Fall des William Penn | Col II --- TaC-Mod | abgebrochen
    Wahnsinn mit Methode? | Col II --- TaC-Mod | beendet | SdM April 2012
    Visiting Vvardenfell | TES III Morrowind | pausiert
    Es war einmal (noch) kein Portugal | Civ IV --- PAE-Mod | beendet
    Pack die Thermohose ein ... | Icewind Dale --- Trials of the Luremaster | läuft
    NEU: [RL] ... wie Gott nach Frankreich - Elwoods ??? | Modellbaubericht | läuft

  2. #17
    Ein Platz an der Sonne Avatar von Commander Bello
    Registriert seit
    05.06.05
    Ort
    Nähe Koblenz
    Beiträge
    6.209
    Oje, das ist ja völlig in Vergessenheit geraten.

    Grob gesagt, stellt sich das Problem dar wie folgt (siehe auch weiter oben das ausführlichere Posting sowie dieses Posting):
    Die Veteran-Beförderung erhöht die Stärke der beförderten Einheit, egal ob sie angreift oder verteidigt.
    Alle anderen (Kampf-)Beförderungen heben oder senken die Stärke des Verteidigers (im Zusammenwirken mit Geländefeldmodifikatoren).

    Beispiel:
    Der Angreifer (A) hat durch "Nicht-Veteran"-Beförderungen (eigentlich) +20% Stärke. Der Verteidiger (V) hat +10% Stärke.
    Es kämpft nun nicht (bei einer Standardstärke von 3) A mit 3,6 gegen V mit 3,3 (Siegeschance 77,3%), sondern
    A mit Stärke 3 gegen V mit Stärke 2,7272....
    Die Siegeschance für A ist in diesem Fall 68,0%.

    Das Ganze ist, wie im oberen Posting dargestellt, ziemlich verwickelt, und erfordert m.E. überflüssige Rechenschritte, deren Sinn ich bis heute nie erkennen konnte.
    Je nachdem, welche der beiden Einheiten die höheren Beförderungswerte (immer daran denken, für den Verteidiger kommen auch die Geländewerte mit dazu!) aufweist, kann die Veteranbeförderung mal besser wirken, und mal geringfügig schlechter (s.o.). Eine allgemeine Aussage kann man daher nicht treffen.

    Ich persönlich bin jedoch der Meinung, dass alle Beförderungen auf das "Veteransystem" umgestellt werden sollten, weil auch die meisten Spieler (fälschlicherweise) davon ausgehen, dass alles so wirkt wie die Veteranbeförderung(en).


  3. #18
    Ein Platz an der Sonne Avatar von Commander Bello
    Registriert seit
    05.06.05
    Ort
    Nähe Koblenz
    Beiträge
    6.209
    Oh Mann, ich muss mir mal Luft machen!

    Dieses Kampfsystem kann sich nur jemand ausgedacht haben, der a) im Vollrausch und b) vom Weltenhass zerfressen war.

    Kleine Kostprobe?

    if (GC.getGameINLINE().getSorenRandNum(GC.getDefineINT("COMBAT_DIE_SIDES"), "Combat") < iDefenderOdds)

    Das ist die Zeile, welche bestimmt, ob der Angreifer einen Treffer landet oder nicht. Wenn er keinen Treffer landet, trifft automatisch der Verteidiger. So gut, so sinnarm, aber das haben wir weiter oben ja schon alles besprochen.
    Nun fragt sich natürlich, was genau sind denn die iDefenderOdds?

    Dazu müssen wir uns die Funktion getDefenderCombatValues(.......) ansehen:
    Code:
    void CvUnit::getDefenderCombatValues(CvUnit& kDefender, const CvPlot* pPlot, int iOurStrength, int iOurFirepower, int& iTheirOdds, int& iTheirStrength, int& iOurDamage, int& iTheirDamage, CombatDetails* pTheirDetails) const
    {
        iTheirStrength = kDefender.currCombatStr(pPlot, this, pTheirDetails);
        int iTheirFirepower = kDefender.currFirepower(pPlot, this);
    
        FAssert((iOurStrength + iTheirStrength) > 0);
        FAssert((iOurFirepower + iTheirFirepower) > 0);
    
        iTheirOdds = ((GC.getDefineINT("COMBAT_DIE_SIDES") * iTheirStrength) / (iOurStrength + iTheirStrength));
        int iStrengthFactor = ((iOurFirepower + iTheirFirepower + 1) / 2);
    
        iOurDamage = std::max(1, ((GC.getDefineINT("COMBAT_DAMAGE") * (iTheirFirepower + iStrengthFactor)) / (iOurFirepower + iStrengthFactor)));
        iTheirDamage = std::max(1, ((GC.getDefineINT("COMBAT_DAMAGE") * (iOurFirepower + iStrengthFactor)) / (iTheirFirepower + iStrengthFactor)));
    }
    Und da geht'sdann richtig los...

    Ich gehe von folgender Kombination aus:
    Angreifer: Stärke 10, 87 Hitpoints (ist halt verwundet, die maximalen Hitpoints sind 100)
    Verteidiger: Stärke 10, 73 Hitpoints (auch verwundet, maximale Hitpoints sind natürlich auch 100)

    iTheirStrength ist in diesem Fall die Stärke des Verteidigers, die sich aus currCombatStr(...) ergibt.
    Achtung Spoiler:
    Code:
    int CvUnit::currCombatStr(const CvPlot* pPlot, const CvUnit* pAttacker, CombatDetails* pCombatDetails) const
    {
        return ((maxCombatStr(pPlot, pAttacker, pCombatDetails) * currHitPoints()) / maxHitPoints());
    }

    maxCombatStr(...) kann ich hier nicht darstellen, das erstreckt sich über 200 Zeilen oder so ähnlich. Für einen Kampf ohne Verteidigungswerte des Geländes und ohne Beförderungen, ohne Eingrabung oder Stadtmauer, ohne Bonus gegen Indianer (schnauf... hab' ich was vergessen?) liefert die Funktion maxCombatStr jedoch die Basisstärke * 100 an currCombatStr zurück.

    Das müsste dann also unter Zugrundelegung obiger Annahmen 10*100*73/100 sein, also 7300.


    Im nächsten Schritt wird dann iTheirFirePower errechnet. Dazu bedarf es der Funktion currFirepower(...)
    Achtung Spoiler:
    Code:
    int CvUnit::currFirepower(const CvPlot* pPlot, const CvUnit* pAttacker) const
    {
        return ((maxCombatStr(pPlot, pAttacker) + currCombatStr(pPlot, pAttacker) + 1) / 2);
    }

    Das ist dann also (maxCombatStr + currCombatStr +1)/2
    (10000 + 7300 + 1)/2 = 8650,5

    Das nehmen wir für den Moment mal kommentarlos so hin, auch wenn die Formel als wenig schlüssig erscheint. Tatsächlich tut sie nur eins, nämlich im Falle verletzter Einheiten deren Stärke künstlich anzuheben.

    Nun geht es endlich an die Wahrscheinlichkeiten.
    Achtung Spoiler:
    Code:
        iTheirOdds = ((GC.getDefineINT("COMBAT_DIE_SIDES") * iTheirStrength) / (iOurStrength + iTheirStrength));
        int iStrengthFactor = ((iOurFirepower + iTheirFirepower + 1) / 2);
    
        iOurDamage = std::max(1, ((GC.getDefineINT("COMBAT_DAMAGE") * (iTheirFirepower + iStrengthFactor)) / (iOurFirepower + iStrengthFactor)));
        iTheirDamage = std::max(1, ((GC.getDefineINT("COMBAT_DAMAGE") * (iOurFirepower + iStrengthFactor)) / (iTheirFirepower + iStrengthFactor)));

    COMBAT_DIE_SIDES ist 1000
    Also:
    1000 * 7300 / (8700+7300) = 456,25 oder mit anderen Worten: der Verteidiger hat eine Wahrscheinlichkeit von ~45,625%, nicht getroffen zu werden und damit selbst zu treffen.

    Das waren die Wahrscheinlichkeiten. Nun geht es um die Schadenspunkte, die dem einen oder dem anderen verpasst werden:

    Dazu wird zunächst der iStrengthFactor berechnet:
    (8700 + 7300 +1) / 2 = 8000,5 Es handelt sich hier um einen Integerwert, also 8000

    Der Schaden, den der Angreifer erleidet, wenn er nicht trifft (p=0,45625), errechnet sich dann also folgendermaßen:
    iOurDamage => der größere Wert von 1 oder 20 * (8650+8000)/(9350+8000) = 19,193... => 19
    iTheirDamage => der größere Wert von 1 oder 20 * (9350+8000)/(8650+8000)= 20,84..... => 20

    Würde man das Ganze ohne die currFirePower und ohne iStrenghtFactor, sondern nur aufgrund der Stärken berechnen, ergäbe sich
    iOurDamage = 16,78 => 16
    iTheirDamage = 23,83 => 23

    Der Witz daran ist, dass die entweder 19/16 oder 20/23 Schadenspunkte aber von den Hitpoints noch abgezogen werden.
    Tatsächlich muss der Angreifer im vorliegenden Fall "bei Colonization" noch 5mal, bei der "einfachen" Variante noch 6mal getroffen werden.
    Der Verteidiger hingegen muss "bei Colonization" 4mal getroffen werden, bei der "einfachen" Variante auch viermal.

    Die ganze Herumspielerei mit FirePower und StrengthFactor hat also m.E. nur das Ziel, den jeweiligen Verteidiger zu bevorteilen, kostet dafür aber Rechenzeit. Ob das sinnvoll ist, wage ich im Moment noch zu bezweifeln.

    Ich werde mir mal überlegen, ob ich das nicht in meiner Mod einfach rauskegele...

    Und wenn ich mir die Zahlen so ansehe, dann frage ich mich, ob man nicht einfach COMBAT_DAMAGE (20) mit der Wahrscheinlichkeit mal 2 multiplizieren sollte (für den Verteidiger: p=0,45625 *2), um die notwendigen Treffer zu berechnen. Das würde dann 18 Schadenspunkte beim Angreifer ergeben und 21 beim Verteidiger, wäre viel kürzer und schneller zu berechnen und macht auf den ersten Blick keinen großen Unterschied aus. Muss ich morgen in einer stillen Stunde noch mal mit einigen anderen Werten durchrechnen ....


  4. #19
    Registrierter Benutzer Avatar von Skyvaheri
    Registriert seit
    06.01.09
    Ort
    Berlin
    Beiträge
    777
    Ich finde es Klasse, dass Du da so in die Tiefe gehst (gehen kannst).

    Natürlich ist so eine Regelung wenn der Angreifer nicht trifft, trifft der Verteidiger realitätsfern.
    Gerade wenn Kontrahenten mit Musketen antreten, die bekanntlich alles andere als zielgenau waren. So sollte es schon möglich sein, dass beide keinen Treffer landen. Gerade bei Deinem Kampfsystem, dass ich nicht als neu sondern auch als sehr interessant empfinde, würde das viel verändern - und ich denke zum positiven.

    Mit einem Fixum von 20 sind sehr starke Einheiten, die gegen viele schwache antreten benachteiligt oder? Das wäre dann eher weniger gut oder?
    Ansonsten gilt natürlich so einfach wie möglich und so kompliziert wie nötig.

  5. #20
    Ein Platz an der Sonne Avatar von Commander Bello
    Registriert seit
    05.06.05
    Ort
    Nähe Koblenz
    Beiträge
    6.209
    Zitat Zitat von Skyvaheri Beitrag anzeigen
    Ich finde es Klasse, dass Du da so in die Tiefe gehst (gehen kannst).
    Danke, aber ehrlichkeitshalber muss ich eingestehen, dass im Moment noch vieles Tasten im Nebel ist...


    Zitat Zitat von Skyvaheri Beitrag anzeigen
    Mit einem Fixum von 20 sind sehr starke Einheiten, die gegen viele schwache antreten benachteiligt oder? Das wäre dann eher weniger gut oder?
    Ansonsten gilt natürlich so einfach wie möglich und so kompliziert wie nötig.
    Die 20 Punkte als Basiswert bedeuten ja den Schaden, den eine Einheit A (z.B. Angreifer) bei einem gleichstarken Gegner V (Verteidiger) pro Treffer verursacht.
    Dieser Wert ist eigentlich gar nicht so schlecht gewählt, weil er dafür sorgt, dass die Kämpfe in einer überschaubaren Anzahl von (internen) Kampfrunden zum Abschluss kommen. Nur die Art und Weise, wie Firaxis da Werte hin und her würfelt, finde ich unnötig kompliziert.
    Allein die Bezeichnung FirePower und StrengthFactor deuten schon darauf hin, dass man zu Beginn noch irgendetwas anderes im Sinne hatte, was dann aber nicht umgesetzt wurde.
    Insgesamt muss ich zugeben, dass ich das Kampfsystem von Col seit Jahren für mehr als verbesserungswürdig halte.

    Ich muss mal ein kleines Excel aufsetzen, um mir das mit einer Reihe anderer Werte (dann auch unter Einbeziehung von Beförderungen etc.) anzusehen. Emoticon: lesen


  6. #21
    Registrierter Benutzer Avatar von Skyvaheri
    Registriert seit
    06.01.09
    Ort
    Berlin
    Beiträge
    777
    Da kannst Du auch gerne mitnehmen. In Sachen Kalkulationen und Statistiken bin ich nicht ganz unbewandert.

  7. #22
    Ein Platz an der Sonne Avatar von Commander Bello
    Registriert seit
    05.06.05
    Ort
    Nähe Koblenz
    Beiträge
    6.209
    Darauf komme ich dann glatt zurück, wenn ich das Excel aufgesetzt habe (nur wird das heute vermutlich nichts mehr).


  8. #23
    Ein Platz an der Sonne Avatar von Commander Bello
    Registriert seit
    05.06.05
    Ort
    Nähe Koblenz
    Beiträge
    6.209
    Oh Mann...

    Das wird immer wüster
    Ungeachtet der Tatsache, dass in der getDefenderCombatValues() die Wahrscheinlichkeit für einen Treffer des Verteidigers (und damit indirekt für den Angreifer ebenfalls) berechnet wird, gibt es in der CvGameCoreUtils.cpp auch noch eine Funktion getCombatOdds(), die das gleiche tut.

    Entweder verstehe ich hier irgendwas noch nicht so ganz (das ist gar nicht mal so unwahrscheinlich...), oder Firaxis hat irgendwann komplett den Überblick verloren.


Seite 2 von 2 ErsteErste 12

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •