Seite 176 von 180 ErsteErste ... 76126166172173174175176177178179180 LetzteLetzte
Ergebnis 2.626 bis 2.640 von 2699

Thema: Der SDK-Fragen-Thread

  1. #2626
    Moderator Avatar von Kathy
    Registriert seit
    11.10.07
    Beiträge
    16.916
    Wäre es nicht besser, m_pFormationType mit dem Wert aus der CivUnitsInfo zu initialisieren? Damit Maschinen FORMATION_TYPE_MACHINE und Menschen FORMATION_TYPE_DEFAULT erhalten?
    That's why I am here: Mein Mod
    Mehr Technologien, mehr Einheiten, mehr Zivilisationen, mehr Gebäude

    Die aktuelle Story zum Mod:
    Die Vereinigten Staaten von Amerika

    Alte Stories zu alten Versionen:
    Alte Storys

  2. #2627
    ε•ω=1 Avatar von Ramkhamhaeng
    Registriert seit
    19.07.10
    Ort
    Aralkum
    Beiträge
    9.896
    Wäre möglich, aber wegen potentiellen Seiteneffekten würde ich das nicht machen. Der Basis-BTS-Code enthält zwar keinen Seiteneffekt, aber es könnte sich beispielsweise der Einheitentyp dynamisch ändern.
    Die Standardvariante von getFormationType ist ja
    Code:
    const char* CvUnit::getFormationType() const 
    {
      return m_pUnitInfo->getFormationType();
    }
    Das ist flexibel und weniger anfällig für Seiteneffekte.
    Gibt IHMO keinen Grund das bei der Initialisierung auf einen fixen Wert zu setzen.

    Bringt die Änderung im Konstruktor eine Verbesserung?

  3. #2628
    Moderator Avatar von Kathy
    Registriert seit
    11.10.07
    Beiträge
    16.916
    Ich glaube schon, dass es jetzt besser ist. Zumindest konnte ich im Weltenbauer 32 Schiffe setzen, ohne dass es abgestürzt ist. Danach habe ich den Versuch beendet. Vorher ist es gerne schon einmal beim 4. abgeschmiert. Ganz sicher sein kann ich mir natürlich nicht.

    Vielen Dank für deine Hilfe.
    That's why I am here: Mein Mod
    Mehr Technologien, mehr Einheiten, mehr Zivilisationen, mehr Gebäude

    Die aktuelle Story zum Mod:
    Die Vereinigten Staaten von Amerika

    Alte Stories zu alten Versionen:
    Alte Storys

  4. #2629
    ε•ω=1 Avatar von Ramkhamhaeng
    Registriert seit
    19.07.10
    Ort
    Aralkum
    Beiträge
    9.896
    Muss nur mal kurz Motzen…

    Aufgrund diverser Probleme mit neueren Visual Studio-Versionen habe ich für Civ4, sonst nutze ich den Krempel ja nicht, noch 'Visual Studio 2010' installiert.
    Dort wollte ich nun eine C-Library von mir einbinden und muss feststellen, dass die 2010er-Version nur den C-Standard C89 unterstützt Da gibt es leider Probleme mit der Definition von Strukturen, die später flexibler wurden.

    Das Umfrickeln der Header in eine konforme Syntax hatte was vom Bau einer Zeitmaschine. Und wie eine Zeitmaschine funktioniert es natürlich danach immer noch nicht.

    Edit: Mittlerweile habe ich es hinbekommen, aber die externe Lib flog kurz darauf wieder raus
    Geändert von Ramkhamhaeng (03. Februar 2019 um 11:19 Uhr)

  5. #2630
    ε•ω=1 Avatar von Ramkhamhaeng
    Registriert seit
    19.07.10
    Ort
    Aralkum
    Beiträge
    9.896
    Bei der Pfadsuche der Einheiten kommt ein *-Algorithmus, ausgehend vom Zielfeld (Z) zum Einsatz.
    Hat mal jemand versucht diese Suche zu invertieren und vom Einheitenfeld (S) auszugehen?

    Bild

    Abstrakter Hintergrund der Frage:
    Ich habe eine Einheit gegeben, die mit einer Eigenschaft X_S ∈ {a₁, a₂,… } auf dem Startfeld S ausgestattet ist.
    In Abhängigkeit vom kürzesten Pfad von S zu Plot P kann ich dem P den Wert X_P zuweisen.
    Am Ende des *-Algos erhalte ich so X_T.

    Beginne ich aber auf dem Zielfeld, bin ich aufgeschmissen, und kann diese Eigenschaft nicht ableiten.


    Konkretes Beispiel:
    Einer Einheit ist eine Kante(=Fluss) zugewiesen. Ich möchte die Einheit nun entlang der Fluss-Kanten bewegen.

  6. #2631
    Civ4 BASE Coder Avatar von rucivfan
    Registriert seit
    10.07.11
    Ort
    Antarktika
    Beiträge
    19.015
    Zitat Zitat von Ramkhamhaeng Beitrag anzeigen
    Bei der Pfadsuche der Einheiten kommt ein *-Algorithmus, ausgehend vom Zielfeld (Z) zum Einsatz.
    Hat mal jemand versucht diese Suche zu invertieren und vom Einheitenfeld (S) auszugehen?
    Irgend ein Mod hatte seine eigene A*-Suche reingecoded bzw habe ich mir den Code dazu mal angesehen. Müsste suchen, welcher das war.

    Ich kenne zu mindest dein Problem [des Invertieren] gut. Um sicher zu gehen, muss der Code eigentlich immer Eigenschaften von Plot Px, von Plot Py und von Plot Px zu Plot Py (Fluss zum Beispiel) abfragen um alle Möglichkeiten abzudecken. Firaxis kam ja nie auf die Idee, dass man canMoveInto nicht nur ein Zielplot brauch. Irgend wo liegt noch Arbeitscode von mir Brach, der das ändern sollte.
    Geändert von rucivfan (03. Februar 2019 um 23:01 Uhr)

  7. #2632
    ε•ω=1 Avatar von Ramkhamhaeng
    Registriert seit
    19.07.10
    Ort
    Aralkum
    Beiträge
    9.896
    Habe mal ein weiter geschaut. Ein großes Problem ist die Pfad-Generierung beim "g"-Befehl. (Hatte dazu, glaube ich, schon mal vor ein paar Jahren was geschrieben )

    In CvSelectionGroup kann man Ziel und Start invertieren.
    Code:
    	gDLL->getFAStarIFace()->SetData(&GC.getPathFinder(), this);
    	bSuccess = gDLL->getFAStarIFace()->GeneratePath(&GC.getPathFinder(), pFromPlot->getX_INLINE(), pFromPlot->getY_INLINE(), pToPlot->getX_INLINE(), pToPlot->getY_INLINE(), false, iFlags, bReuse);
    Hier könnte ich das Problem vermutlich lösen.
    Aber beim "g"-Menu ruft die Exe(!) nicht getPathFinder() sondern getInterfacePathFinder() auf, und mit diesem dann GeneratePath...

  8. #2633
    Registrierter Benutzer
    Registriert seit
    21.03.12
    Beiträge
    22.397
    Der Algorithmus heißt A* Unter Civ-Bedingungen ist der grundsätzlich nicht reziprok, vom Hügel runter braucht weniger BP als auf den Hügel hoch.

    Mach doch mal bitte eine Zeichnung, welches Problem gelöst werden soll.

  9. #2634
    ε•ω=1 Avatar von Ramkhamhaeng
    Registriert seit
    19.07.10
    Ort
    Aralkum
    Beiträge
    9.896
    Das mit den Hügeln stimmt, aber wenn man die Felder in der Kostenfunktion auch invertiert, solle die invertierte Reihenfolge die gleichen Bewegungskosten erzeugen.

    Skizzierung des Problems/Rule sets.

    1. Schiffen wird auf Landfeldern eine Kante zugeordnet¹. Sie dürfen auf Ozeanfelder, Städte & Festungen (wie bisher) ziehen, aber
    sich nun auch noch entlang von Flußkanten bewegen.
    (=> Auf andere, an das gleiche Feld grenzende, Flüsse darf nicht gesprungen werden.)

    2. Die Bewegungskosten werden pro benutzter Flußkante berechnet, nicht pro Feld.
    (Die Funktion für die passenden Transitionskosten (und weiteren Meta-Daten) habe ich auch bereits erstellt.)

    Mein derzeitiger Kommentar im Code dazu.
    Den aber nicht zu wörtlich nehmen, da alles noch „im Fluss“, um im Bilde zu bleiben Beispielsweise wird am Anfang noch von NORTH, etc. geschrieben während es später NORTH_CW, NORTH_CCW, etc sind. Da habe ich später den vier Kanten noch eine Ausrichtung gegeben (D.h. es sind 8 Fälle.)
    Achtung Spoiler:
    Code:
      /* Loop over plots and generate cost-map(s) and positions-map(s).
       *
       * The cost-maps are stored on fields with rivers, thus if you want enter a plot,
       * you need a lookup into the target field cost-map, if the source field
       * is without a map.
       * */
      /* Example movement cost map if ship (S) is at 'north edge of plot X' and all edges are rivers:
       * (The cost map only stores the plot values.
       *  Edge values included just for demonstration purposes.)
       *
       *  1  1  0  1  1 <-- plot(X+1,Y+1)
       *  1     S     1 <-- edge
       *  1  1  X  1  1
       *  2     2     2
       *  2  2  2  2  2 
       *
       * Matching position map. It stores the direction(s), a ship could take if it moves 
       * into the field in this direction.
       * Note the quantum-state like behaviour: It is not clear which edge a ship will use
       *      unless the next plot of the path is evaluated!
       *
       * SOUTH|EAST       SOUTH       SOUTH|WEST 
       *                    S
       * NORTH|EAST         X         NORTH|WEST
       *
       * NORTH|EAST  NORTH|EAST|WEST  NORTH|WEST
       *
       *
       * Example movement costs map if only a few edges are rivers. Here, we need to circle
       * around plot X before we can move to the left.
       *
       *  F0    0    F0
       *        S    
       *  3     X  1  1
       *  3     2     
       *  3     2  2  2 
       *
       * Matching position map.
       *
       * {empty}          SOUTH       {empty} 
       *                    S
       * SOUTH              X         WEST
       *
       * NORTH       NORTH|EAST       WEST
       *
       * Finally, we need a map which stores the possible directions, if we
       * move into a field, but the source field is without river.
       *
       * Example:
       *   NW     N    NE     —: River
       *          — ₀
       *    W     X |   E 
       *          — ₀
       *   SW     S    SE
       *
       *
       * NORTH_          EAST_CW|NOR…  NORTH_CCW|EAST_CW
       *                    
       * NORTH_CW|SOUTH_CCW     X      NORTH_CCW|SOUTH_CW|EAST_CW|EAST_CCW
       *
       * SOUTH_CCW       EAST_CCw|NOR… EAST_CCW|SOUTH_CW
       *
       */


    3. Nur wenn die Route für die nächsten zwei Felder definiert ist, kann man für das mittlere Feld die minimalen Kosten berechnen.
    Steht man beispielsweise auf der Nordkante von Plot1, kann man auf zwei Arten nach Plot2, ziehen, aber minimale Kosten bei der Bewegung nach Plot3 hat man nur bei einer Variante.
    Code:
    =======  =======
      ^^   ||
    {Plot1}||{Plot2}
           ||
           ||
           ||{Plot3}
           ||
    
    
    =,|| — Flusskante,
    ^^ — Startposition
    Statt einem Schiff also eine Kante zuzuweisen, ist es hilfreich während der Pfadberechnung mehrere mögliche Kanten (Quantenzustand ^^) als Ort für das Schiff anzunehmen und sich dann bei der Bewegung nach Plot 3 für die billigste zu entscheiden.
    Ich bin mir noch nicht sicher, ob man diesen Quantenzustand beibehält, wenn der Spieler in Plot2 zwischenhält, oder ob man sich dann für eine Variante entscheiden (Der Spieler beobachtet das Schiff ja ^^).
    Wenn man sich dann aber zufällig für eine Kante entscheidet, kann das die Kosten erhöhen.
    Das könnte den Spieler verwundern.



    Hier nun mal ein Beispiel, was das Backtracking-Problem beim jetzigen A*-Algo zeigt:
    Code:
             ======  ======  ======  ======
           ||                              ||
           ||         {X2}                 ||
           ||                              ||
    =======          ======          ======
      ^^           ||      ||          °°
    {Start}        ||      || {X1}   {Targ.}
                   ||      ||
                             ======  ======
                   ||
                   ||
                   ||
    Das Schiff soll von Kante '^^' zu '°°' ziehen und der Spieler klickt auf das Target-Feld.
    Speichert man nun immer nur die Daten mit den minimalen Kosten zwischen,
    so wird man beim Backtracking auf Feld X2 die Kosten für den südlicheren Fluss gespeichert
    haben.
    Ab da ist es, auf dem Weg zum Start-Plot, nicht mehr möglich die korrekten Kosten zu rekonstrieren.

  10. #2635
    ε•ω=1 Avatar von Ramkhamhaeng
    Registriert seit
    19.07.10
    Ort
    Aralkum
    Beiträge
    9.896
    Zitat Zitat von Ramkhamhaeng Beitrag anzeigen
    In CvSelectionGroup kann man Ziel und Start invertieren.
    PHP-Code:
        gDLL->getFAStarIFace()->SetData(&GC.getPathFinder(), this);
        
    //bSuccess = gDLL->getFAStarIFace()->GeneratePath(&GC.getPathFinder(), pFromPlot->getX_INLINE(), pFromPlot->getY_INLINE(), pToPlot->getX_INLINE(), pToPlot->getY_INLINE(), false, iFlags, bReuse);
        
    bSuccess gDLL->getFAStarIFace()->GeneratePath(&GC.getPathFinder(), pToPlot->getX_INLINE(), pToPlot->getY_INLINE(), pFromPlot->getX_INLINE(), pFromPlot->getY_INLINE(), falseiFlagsbReuse); 
    Wenn ich das zugehörige Auslesen des Pfades auch invertiere scheint das schon zu klappen
    Das mit den Hügel-Kosten, etc muss ich aber noch abklopfen.
    PHP-Code:
    #if 0
    FAStarNodeCvSelectionGroup::getPathLastNode() const
    {
        return 
    gDLL->getFAStarIFace()->GetLastNode(&GC.getPathFinder());
    }


    CvPlotCvSelectionGroup::getPathFirstPlot() const
    {
        
    FAStarNodepNode;

        
    pNode getPathLastNode();

        if (
    pNode->m_pParent == NULL)
        {
            return 
    GC.getMapINLINE().plotSorenINLINE(pNode->m_iXpNode->m_iY);
        }

        while (
    pNode != NULL)
        {
            if (
    pNode->m_pParent->m_pParent == NULL)
            {
                return 
    GC.getMapINLINE().plotSorenINLINE(pNode->m_iXpNode->m_iY);
            }

            
    pNode pNode->m_pParent;
        }

        
    FAssert(false);

        return 
    NULL;
    }

    CvPlotCvSelectionGroup::getPathEndTurnPlot() const
    {
        
    FAStarNodepNode;

        
    pNode getPathLastNode();

        if (
    NULL != pNode)
        {
            if ((
    pNode->m_pParent == NULL) || (pNode->m_iData2 == 1))
            {
                return 
    GC.getMapINLINE().plotSorenINLINE(pNode->m_iXpNode->m_iY);
            }

            while (
    pNode->m_pParent != NULL)
            {
                if (
    pNode->m_pParent->m_iData2 == 1)
                {
                    return 
    GC.getMapINLINE().plotSorenINLINE(pNode->m_pParent->m_iXpNode->m_pParent->m_iY);
                }

                
    pNode pNode->m_pParent;
            }
        }

        
    FAssert(false);

        return 
    NULL;
    }
    #else
    /* Flip start and end of path. Required if GeneratePath plots are filpped. */

    // Helper function
    FAStarNode/*CvSelectionGroup::*/getPathFirstNode() //const
    {
        
    FAStarNodepNode;
        
    pNode gDLL->getFAStarIFace()->GetLastNode(&GC.getPathFinder());

        while (
    pNode->m_pParent != NULL)
        {
            
    pNode pNode->m_pParent;
        }
        
    FAssert(pNode != NULL);
      return 
    pNode;
    }

    FAStarNodeCvSelectionGroup::getPathLastNode() const
    {
        return 
    getPathFirstNode();
    }

    CvPlotCvSelectionGroup::getPathFirstPlot() const
    {
        
    FAStarNodepNode;
        
    pNode gDLL->getFAStarIFace()->GetLastNode(&GC.getPathFinder());
        if( 
    pNode == NULL || pNode->m_pParent == NULL){
          return 
    NULL;
      }
      
    pNode pNode->m_pParent;
      return 
    GC.getMapINLINE().plotSorenINLINE(pNode->m_iXpNode->m_iY);
    }

    CvPlotCvSelectionGroup::getPathEndTurnPlot() const
    {
        
    FAStarNodepNode;

        
    pNode gDLL->getFAStarIFace()->GetLastNode(&GC.getPathFinder());

        if (
    NULL != pNode)
        {
            
    //TODO "max-1" statt 1 als Abbruchkriterium?
            
    if ((pNode->m_pParent == NULL) || (pNode->m_iData2 == 1))
            {
                return 
    GC.getMapINLINE().plotSorenINLINE(pNode->m_iXpNode->m_iY);
            }

            while (
    pNode->m_pParent != NULL)
            {
            
    //TODO "max-1" statt 1 als Abbruchkriterium?
                
    if (pNode->m_pParent->m_iData2 == 1)
                {
                    return 
    GC.getMapINLINE().plotSorenINLINE(pNode->m_pParent->m_iXpNode->m_pParent->m_iY);
                }

                
    pNode pNode->m_pParent;
            }
        }

        
    FAssert(false);

        return 
    NULL;
    }
    #endif 

  11. #2636
    Civ4 BASE Coder Avatar von rucivfan
    Registriert seit
    10.07.11
    Ort
    Antarktika
    Beiträge
    19.015
    Ehrlich gesagt, sehe ich keinen Vorteil einer Invertierung. Auf jeden Fall wird das eine lustige Sache, da eine Einheit ja einen Plot zugeordnet sein muss aus Verwaltungstechnischen Gründen und auch um sie anzugreifen.

  12. #2637
    Moderator Avatar von Kathy
    Registriert seit
    11.10.07
    Beiträge
    16.916
    Ich bin jedenfalls gespannt, wie das bei dir läuft. Es klingt sehr interessant und ist natürlich auch realistischer als das, was ich derzeit mit meinen Flussschiffen mache. Aber einen hilfreichen Beitrag kann ich, fürchte ich, hier nicht machen.
    That's why I am here: Mein Mod
    Mehr Technologien, mehr Einheiten, mehr Zivilisationen, mehr Gebäude

    Die aktuelle Story zum Mod:
    Die Vereinigten Staaten von Amerika

    Alte Stories zu alten Versionen:
    Alte Storys

  13. #2638
    ε•ω=1 Avatar von Ramkhamhaeng
    Registriert seit
    19.07.10
    Ort
    Aralkum
    Beiträge
    9.896
    Zitat Zitat von rucivfan Beitrag anzeigen
    Ehrlich gesagt, sehe ich keinen Vorteil einer Invertierung.
    Der Vorteil ist, dass ich die erlaubten Kanten eines Feldes kenne.

    Gehen wir es mal an einem, ans vorherige angelehnte, Beispiel durch.
    N_i sind die Nachbarfelder des Starts.
    N3 ist nicht direkt erreichbar, aber über eine Schleife des Flusses.
    Nun wollen wir die Kosten bis zu N3 ermitteln.

    Code:
             ======  ======  ======  ======
           ||                              ||
      N1   ||  N2      X2      Y1      Y2  ||
           ||                              ||
    =======          ======          ======
      ^^           ||      ||      ||  °°  ||
    {Start}    N3  || Berg ||  X1  ||  Y3  ||
                   ||      ||      ||      ||
                             ======  ======
                   ||
      N4       N5  ||
                   ||
    • Der Test der Vorbedingung canMoveInto(N3, ...) liefert True, da N3 eine Flusskante hat.
    • Die Kosten für die N_i werden berechnet:
      • N1 ist mit Kosten 0 (intern 1/60-Bewegungspunkt, um unendliche Schleifen zu vermeiden.) erreichbar. (Das sollte ggf. noch mal überdacht/verfeinert werden, da es den A*-Algo ausbremmst.)
      • N2 ist auf einer Kante mit den Kosten 1 erreichbar. Die (Kante, unitID) wird im CvPlot-Objekt zwischengespeichert.
      • N3-N5 erhalten die Kosten 'unendlich', da kein direkter Weg existiert.
    • Der A*-Algo geht zum Plot mit den geringsten Kosten, N2. Von dort kann nur X2 erreicht
      werden, wobei diesmal die Kosten 2 betragen, da die Zwischenwerte die Westkante als Start vorgeben.
    • Y1 wird mit Kosten 1 erreicht.
    • Y2 wird mit Kosten 1 erreicht.
    • Y3 wird mit Kosten 2 und zwei möglichen Zielkanten erreicht.
    • X1 kann nun mit Kosten 1 oder 2 erreicht werden, je nachdem ob man an der Nord- oder Ost-Kante von Y3 startet.
    • Jetzt haben wir ein ungelöstes Problem: X2 ist schon abgehandelt und kann nicht erneut betreden werden (TODO ^^) Ignorieren wird das mal...
    • N3 wird von X2 aus erreicht.

  14. #2639
    Civ4 BASE Coder Avatar von rucivfan
    Registriert seit
    10.07.11
    Ort
    Antarktika
    Beiträge
    19.015
    Wenn der Fluss nördlich von X2 zu X2 gehört, müsste der Fluss südlich logisch folgend zu den Feld Berg gehören. X2 kommt doch nur einmal vor.

  15. #2640
    ε•ω=1 Avatar von Ramkhamhaeng
    Registriert seit
    19.07.10
    Ort
    Aralkum
    Beiträge
    9.896
    Bei Civ4 sind die Flüsse intern immer einem Feld zugeordnet, aber hier sollten sie als beiden Nachbarfeldern zugehörig angesehen werden.

    Auf das Feld von X1 habe ich einen Berg gesetzt, um zu verdeutlichen, dass dieses Feld nicht betreten werden kann. Dann würde das „Problem“ des A*-Algo, dass er kein Feld zweimal abarbeiten kann, nicht zum tragen kommen.

Seite 176 von 180 ErsteErste ... 76126166172173174175176177178179180 LetzteLetzte

Berechtigungen

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