Latest Posts

Topic: Mauern Skript

Teayo
Avatar
Topic Opener
Joined: 2015-03-09, 22:11
Posts: 220
OS: Windows 11 Home 64-bit
Version: 1.2.1~rc1
Ranking
Widelands-Forum-Junkie
Location: Deutschland
Posted at: 2024-09-05, 16:43

@Nordfriese , @hessenfarmer

Gebäude Mauerbauer

"findobject=empire_plus_immovable_wall_place_marker radius:15",
"findspace=size:any radius:15 space no_notify",
"return=skipped unless object_or_coords",
"return=failed unless site has empire_plus_ware_granite:1",
"return=failed unless site has empire_plus_ware_cement:1",
"return=failed unless site has empire_plus_ware_water:1",
"consume=empire_plus_ware_cement:1 empire_plus_ware_water:1"
"playsound=sound_name:moertel_anruehren priority:100% allow_multiple",
"animate=working duration:5s",
"produce=empire_plus_ware_bucket:1",
"produce=empire_plus_ware_sack:1",
"unselect=",
"construct=empire_plus_immovables_wall_01i64_v0_t1_r1_e0_ne0_nw0_se0_sw0_w0 worker:create_wall radius:15",
"sleep=duration:5s",
"return=completed"

Wie funktioniert findobject und findspace ?

Ich wollte schon das Programm für den Arbeiter hier posten , aber zuerst muss alles über das Programm für das Gebäude abgeklärt sein ,
den das Arbeiter Programm ist ja dem Gebäude Programm untergeordnet .

Ich gehe davon aus das "findobject" wie folgt funktioniert :
* Kopiere alle Einträge aus der Welt-Objekte Liste , deren Position innerhalb des im Parameter angegebenen Radius liegt , in Liste 2 .
* Kopiere den Eintrag aus der Liste 2 , dessen Position am nächsten zur Position die diesen Befehl ausführt , in die Liste 3 .
* Verschiebe den Eintrag aus der Welt-Objekte Liste , der mit dem Eintrag in der Liste 3 übersteinstimmt , in die Liste der Ausgewählten-Welt-Objekte .
* Speichere zusätzlich beim verschieben in den Eintrag der in die Liste der Ausgewählten-Welt-Objekte Liste verschoben wird , die Verknüpfung , also welches Objekt diesen Befehl ausführt .
* Andere Objekte können nun nicht mehr das ausgewählte Objekt auswählen , da es sich nicht mehr in der Liste der Welt-Objekte befindet .
* Falls das Objekt dass das andere nun nicht mehr auswählbare Objekt nicht mehr existiert oder einen Programm fehlschlag bekommt ,
verschiebe den Eintrag in der Liste der Ausgewählten-Welt-Objekte , der mit dem nicht mehr existierenden Objekt oder mit Programm fehlschlag verknüpft ist , zurück in die Liste der Welt-Objekte .

Ich gehe davon aus das "findspace" wie folgt funktioniert :
* Kopiere alle Einträge aus der Liste Welt-Punkte in die Liste 2 .
* Kopiere alle Einträge aus der Liste 2 , dereren Position innerhalb des im Parameter angegebenen Radius liegt , in die Liste 3 .
* Kopiere alle Einträge aus der Liste 3 , die nicht die Eigenschaften haben die im Paramter angegeben sind , in die Liste 4 .
* Kopiere den Eintrag aus der Liste 4 , dessen Position am nächsten zur Position die diesen Befehl ausführt , in die Liste 5 .
* Bearbeite den Eintrag aus der Liste der Welt-Punkte , der mit dem Eintrag in der Liste 5 übereinstimmt , und füge dem Eintrag die Eigenschaften hinzu :
Ausgewählter-Punkt sowie die Verknüpfung , welches Objekt diesen Punkt ausgewählt hat .

Zudem würde ich die produce Aktionen lieber hinter die construct Aktion verschieben ,
aber wenn ich das mache , dann werden die Waren vernichtet , wenn es zu einen Fehlschlag in der construct Aktion kommt .

Die unselect Aktion ist dafür da das die construct Aktion das Objekt oder den freien Platz wieder auswählen kann (Als Arbeiter ausgeführt) .
Ich muss wissen ob es für andere Objekte noch möglich ist ein Objekt oder einen Punkt zu finden ,
wenn dieser vorher durch ein anderes Objekt mittels findobject Aktion oder findspace Aktion ausgewählt wurde .

Edited: 2024-09-05, 16:47

Top Quote
Nordfriese
Avatar
Joined: 2017-01-17, 18:07
Posts: 2054
OS: Debian Testing
Version: Latest master
Ranking
One Elder of Players
Location: 0x55555d3a34c0
Posted at: 2024-09-05, 17:16

Wenn du schon eine sehr technisch-algorithmische Beschreibung willst, warum liest du nicht direkt den Quelltext? face-wink.png

Denk nicht, dass wir häufiger über irgendwelche Welt-Objekt-Listen oder Welt-Punkte-Listen iterieren, wenn es sich irgendwie vermeiden lässt. Es gibt auf einer großen Karte bis zu 262144 Felder und oft hunderttausende Objekte, und solche Programme werden entsprechend sehr oft ausgeführt; und Algorithmen, die in relativ kleinen Kartenbereichen arbeiten, wurden natürlich damit für Performanz optimiert.

findobject
https://codeberg.org/wl/widelands/src/commit/468b108ba0f8a7085908b80ccf96aed19ca3465d/src/logic/map_objects/tribes/worker.cc#L301-L428
erstellt zunächst eine Liste aller Objekte, die allen Suchkriterien genügen und vom Arbeiter aus erreichbar sind und vom Spieler als zur zeitnahen Entfernung markiert wurden, in einem Umkreis vom Arbeiter mit dem eingestellten Höchstradius. Wenn welche gefunden werden, wird ein zufälliges davon ausgewählt. Ansonsten:
erstellt es eine Liste aller Objekte, die allen Suchkriterien genügen und vom Arbeiter aus erreichbar sind, in einem Umkreis vom Arbeiter mit Radius 0. Wenn mindestens gefunden wird, wird ein zufälliges davon ausgewählt und der Programmschritt als erfolgreich beendet. Wenn keines gefunden wird, dann suche erneut mit Radius 1. Wenn wieder keines gefunden wird, dann mit Radius 2. Und so weiter. Wenn der eingestellte Maximalradius überschritten wird, wird das Programm als fehlgeschlagen abgebrochen.
Der Radius bezieht sich hierbei nicht auf Luftdistanz, sondern die Anzahl der Schritte, die der Arbeiter zurückzulegen hat, also werden Hindernisse und unbegehbares Gelände auch berücksichtigt.
Wenn ein Objekt ausgewählt wird, wird es sofort als "reserviert" markiert. Bereits reservierte Objekte werden beim Suchen immer übersprungen. Feste Objekte (jedoch keine Bobs) auf Feldern, die der Spieler nie gesehen hat ("unexplored"), werden ebenfalls übersprungen.

findspace
https://codeberg.org/wl/widelands/src/commit/468b108ba0f8a7085908b80ccf96aed19ca3465d/src/logic/map_objects/tribes/worker.cc#L510-L992
macht es ein bisschen einfacher.
Es erstellt einfach eine Liste aller Felder, die allen Suchkriterien genügen und vom Arbeiter aus erreichbar sind in einem Umkreis vom Arbeiter mit dem eingestellten Höchstradius (wiederum unter Berücksichtigung von Hindernissen und Geländebegehbarkeit). Wenn welche gefunden werden, wird ein zufälliges davon ausgewählt – jedoch ohne Bias für näher gelegene Felder. Ansonsten Fehlschlag.
Lediglich der Förster (Parameter "saplingsearches") schaut sich mehrere zufällig ausgewählte Kandidaten-Felder an und wählt von diesen das beste aus.
Felder können anders als Objekte nicht reserviert werden, und auch die Sichtbarkeit wird nicht überprüft.

construct
https://codeberg.org/wl/widelands/src/commit/468b108ba0f8a7085908b80ccf96aed19ca3465d/src/logic/map_objects/tribes/worker.cc#L1156-L1195
beachte insbesondere die Platzierung der Zeile imm->set_reserved_by_worker(false)

Edited: 2024-09-05, 17:19

Top Quote
Teayo
Avatar
Topic Opener
Joined: 2015-03-09, 22:11
Posts: 220
OS: Windows 11 Home 64-bit
Version: 1.2.1~rc1
Ranking
Widelands-Forum-Junkie
Location: Deutschland
Posted at: 2024-09-05, 22:08

Oke das sind schonmal gute Nachrichten .
Dann benötige ich keinen Bearbeitungs Schutz vor anderen Objekten für die Mauer Objekte , da das ja schon findobject macht .

Oke das mit findspace kann ich akzeptieren .
Primär soll der Maurer zuerst zum Marker gehen und das ist ein Objekt und wenn kein Marker existiert , weil schon alle Marker in Mauern umgewandelt wurden oder
der Spieler es mit den Mauern doch nicht so eilig hat und noch keine Marker gesetzt hat , dann kann der Maurer auch das bereits geringe Risiko eingehen ,
das wenn er am vormals freien Punkt ankommt , dieser zwischenzeitlich doch bearbeitet wurde und der Maurer nun doch keine Mauer mehr dort errichten kann .

Wenn ich das richtig sehe , dann kann ich das Programm für das Mauerbauer Gebäude so direkt schon lassen .
Die unselect Aktion wird ja weiterhin benötigt da das Gebäude und der Arbeiter zwei verschiedene Objekte sind und die Auswahl bei der construct Aktion nicht übergeben wird .
Und die Auswahl nur mit dem Gebäude verknüpft ist . Die construct Aktion des Gebäudes verstehe ich so das sie :
* consume=<...>
* callworker=<wert_von_parameter:worker>
* findspace=size:<unbekannter_festeingestellter_wert> radius:<wert_von_parameter:radius> space? no_notify?
* findobject=<wert_von_paramter:=>
* createware=<...>
Aber das mit der construct Aktion ist für mich nicht mehr relevant .

Arbeiter Maurer

"walk=object-or-coords",
-- Korrektur der bei construct Aktion des Gebäudes : construct=empire_plus_immovable_wall_place_marker ...
-- empire_plus_immovable_wall_place_marker , build_cost : [ empire_plus_ware_granite:1 ]
"plant=empire_plus_immovables_wall_place_marker unless object",
"findobject=empire_plus_immovables_wall_place_marker radius:0",
"construct",
-- empire_plus_immovables_wall_place_marker ---> empire_plus_immovables_wall_construction_site

"createbob=empire_plus_worker_wall_impulse_add_east",
"createbob=empire_plus_worker_wall_impulse_add_north_east",
"createbob=empire_plus_worker_wall_impulse_add_north_west",
"createbob=empire_plus_worker_wall_impulse_add_south_east",
"createbob=empire_plus_worker_wall_impulse_add_south_west",
"createbob=empire_plus_worker_wall_impulse_add_west",

    -- empire_plus_worker_wall_impulse_add_<Richtung> :
    main :
    {
        "walk=<Richtung> ignore:object_size call_on_failure:remove_object",
        -- Oder statt ignore:object_size kann auch ignore:any , dann wird kein call_on_failure benötigt ,
        -- da logischerweise bei Wasser dann spätestens bei findobject das call_on_failure zutrifft
        "findobject=attrib:empire_plus_walls radius:0 call_on_failure:remove_object",
        "animate=idle duration:90s",
        "call=remove_object"
    },
    remove_object :
    {
        "remove"
    },
    ...

"animate=prepare_for_work duration:2s",
"findobject=empire_plus_immovables_wall_construction_site radius:0",
"callobject=starting_add_center",
-- empire_plus_immovables_wall_construction_site ---> animate add_center 10.1s , transform empire_plus_immovables_wall_place_marker 
"playsound=sound_name:mauer_bauen priority:100% allow_multiple",
"animate=work duration:10s",
"callobject=finishing_add_center",
-- Falls das Mauerbauer Gebäude abgerissen oder zerstört wird , bevor die Mauer fertig gebaut wurde
-- empire_plus_immovables_wall_construction_site ---> empire_plus_immovables_wall_01i64_v0_t1_r1_e0_ne0_nw0_se0_sw0_w0

"call=continue_east",
"call=continue_north_east",
"call=continue_north_west",
"call=continue_south_east",
"call=continue_south_west",
"call=continue_west",
"return"

continue_<Richtung> :
    {
    "findobject=empire_plus_worker_wall_impulse_add_<Richtung> radius:1 programm_success_on_programm_failure",
    "callworker=starting_change",
    "findobject=attrib:empire_plus_walls radius:0",
    "callobject=starting_add_<Richtung>",
    "playsound=sound_name:mauer_bauen priority:100% allow_multiple",
    "animate=work duration:10s",
    "callobject=finishing_add_<Richtung>",
    "findobject=empire_worker_object_wall_impulse_add_<Richtung>
    "callworker=finishing_change",
    -- Das programm_success kann auch hier stehen , da bei einen Fehlschlag alle Aktionen im Programm mit der Bedingung success=1 nicht mehr ausgeführt werden ,
    -- jedoch die Zeilen weiter nach unten durchläuft bis die return Aktion erreicht wurde , die als Bedingung success=0..1
    -- hat also die unabhängig vom success Wert immer ausgeführt wird .
    -- Jedoch darf das übergenordnete success vom übergeordneten Programm nicht durch das success von diesen Programm überschrieben werden .
    },

-- empire_plus_worker_wall_impulse_add_<Richtung> :
    ...,
    starting_change :
    {
        "findobject=attrib:empire_plus_walls radius:0",
        "callobject=starting_add_<Richtung>",
        "animate=idle duration:11s",
        "call=remove_object"
    },
    finishing_change :
    {
        "findobject=attrib:empire_plus_walls radius:0",
        "callobject=finishing_add_<Richtung>",
        "call=remove_object"
    },

So sollte das Arbeiter Programm aussehen . Ich bin mir sicher ich habe einige Probleme und Sonderfälle übersehen .
Einen Fall den ich bewusst ausgelassen habe ist , wenn das Mauerbauer Gebäude abgerissen oder zerstört wird , nachdem das Mauer Zentrum steht ,
jedoch bevor alle Verbindungen zu den anderen Mauer Objekten stehen .
Das hätte zur folge das die Mauer funktionell funktioniert und den Weg für Gegner blockiert , jedoch wäre eine graphische Lücke / unstimmigkeit zu sehen ,
da die graphische Verbindung noch fehlt .
Darüber muss ich noch nachdenken und zusätzlich eure Rückmeldungen einholen .

Die Wechselwirkungen von zwei Maurern die zufälligerweise nebeneinander die Mauern bearbeiten oder gar wenn Steinhauer neben einen Maurer arbeiten ,
habe ich jetzt noch nicht betrachtet , hier muss ich mir nochmal den Bearbeitungsschutz genau ansehen , doch findobject gibt mir da schon etwas vertrauen .
Es wird in jeden Fall kompliziert .


Top Quote
hessenfarmer
Avatar
Joined: 2014-12-11, 23:16
Posts: 2743
Ranking
One Elder of Players
Location: Bavaria
Posted at: 2024-09-05, 23:51

2 kleine aber wichtige Ergänzungen meinerseits:
"findobject" und "findspace" sind nur für Arbeiter definiert und können von Gebäuden nicht direkt aufgerufen werden.
Eine Aktion "unselect" ist nicht definiert.


Top Quote
Teayo
Avatar
Topic Opener
Joined: 2015-03-09, 22:11
Posts: 220
OS: Windows 11 Home 64-bit
Version: 1.2.1~rc1
Ranking
Widelands-Forum-Junkie
Location: Deutschland
Posted at: 2024-09-06, 00:22

@hessenfarmer und wie würdest du dann das folgende Problem lösen ?
- Die Waren sollen erst verbraucht werden , wenn es auch wirklich eine Mauer zu bauen gibt .

"callworker=check_can_wall_build",
    "findobject=empire_plus_immovable_wall_place_marker radius:15",
    "findspace=size:any radius:15 space no_notify",
    "return"
"return=skipped unless object_or_coords",
"return=failed unless site has empire_plus_ware_water:1",
...
Edited: 2024-09-06, 00:26

Top Quote
hessenfarmer
Avatar
Joined: 2014-12-11, 23:16
Posts: 2743
Ranking
One Elder of Players
Location: Bavaria
Posted at: 2024-09-06, 11:15

Teayo wrote:

@hessenfarmer und wie würdest du dann das folgende Problem lösen ?
- Die Waren sollen erst verbraucht werden , wenn es auch wirklich eine Mauer zu bauen gibt .

Genauso wie du das hier skizzierst, durch Aufruf eines Programms des Arbeiters, welches die Vorrasusetzung checkt (siehe z.B. auch der friesische Deichbauer)

~~~~ "callworker=check_can_wall_build", "findobject=empire_plus_immovable_wall_place_marker radius:15", "findspace=size:any radius:15 space no_notify",

die Aneinanderreihung dieser Abfragen liefert (imho) immer nur eine Koordinate, da findspace das Resultat von findobject überschreibt.

"return"

return im programm eines Arbeiters bedeutet, dass er von wo auch immer nach Hause geht. das ist bei reinen "find..." tasks nicht notwendig weil er dafür das Haus nicht verlässt.

"return=skipped unless object_or_coords",

wie oben beschrieben funktioniert object_or_coords nur mit dem Programm "construct"

"return=failed unless site has empire_plus_ware_water:1", ... ~~~~


Top Quote
Teayo
Avatar
Topic Opener
Joined: 2015-03-09, 22:11
Posts: 220
OS: Windows 11 Home 64-bit
Version: 1.2.1~rc1
Ranking
Widelands-Forum-Junkie
Location: Deutschland
Posted at: 2024-09-08, 12:58

Überarbeitete Skripte

Gebäude Mauerbauer

main :
"call=wall_build_from_object",
"call=wall_build_from_space"

wall_build_from_space :
"callworker=check_area_space",
"consume=empire_plus_ware_cement:1 empire_plus_ware_water:1 empire_plus_ware_granite:1",
"playsound=sound_name:moertel_anruehren priority:100% allow_multiple",
"animate=working duration:5s",
"callworker=build_wall_from_space",
"produce=empire_plus_ware_bucket:1 empire_plus_ware_sack:1",
"sleep=duration:5s"

wall_build_from_object :
"callworker=check_area_object",
"consume=empire_plus_ware_cement:1 empire_plus_ware_water:1 empire_plus_ware_granite:1",
"playsound=sound_name:moertel_anruehren priority:100% allow_multiple",
"animate=working duration:5s",
"callworker=build_wall_from_object",
"produce=empire_plus_ware_bucket:1 empire_plus_ware_sack",
"sleep=duration:5s",
"return=completed",
"call=wall_build_from_object"

Arbeiter Maurer

check_area_space :
"findspace=size:any radius:15 space"

check_area_object :
"findobject=empire_plus_immovable_wall_place_marker radius:15"

build_wall_from_space :
"findspace=size:any radius:15 space",
"createware=empire_plus_ware_granite",
"walk=coords",
"plant=empire_plus_immovable_wall_construction_01i64_v0_t1_r1_e0_ne0_nw0_se0_sw0_w0",
"findobject=empire_plus_immovable_wall_construction_01i64_v0_t1_r1_e0_ne0_nw0_se0_sw0_w0",
"construct",
--"deleteware",
"createbob=empire_plus_worker_wall_impulse_add_east",
"createbob=empire_plus_worker_wall_impulse_add_north_east",
"createbob=empire_plus_worker_wall_impulse_add_north_west",
"createbob=empire_plus_worker_wall_impulse_add_south_east",
"createbob=empire_plus_worker_wall_impulse_add_south_west",
"createbob=empire_plus_worker_wall_impulse_add_west",
"playsound=sound_name:mauer_bauen priority:100% allow_multiple",
"animate=working duration:5s",
"callobject=constrution_completed",
"call=add_wall_connection_to_east skip_this_action_on_failure",
"call=add_wall_connection_to_north_east skip_this_action_on_failure",
"call=add_wall_connection_to_north_west skip_this_action_on_failure",
"call=add_wall_connection_to_south_east skip_this_action_on_failure",
"call=add_wall_connection_to_south_west skip_this_action_on_failure",
"call=add_wall_connection_to_west skip_this_action_on_failure",
"return"

wall_build_from_object :
"findobject=empire_plus_immovable_wall_place_marker radius:15",
"createware=empire_plus_ware_granite",
"walk=object",
"callobject=transform_into_wall",
"findobject=empire_plus_immovable_wall_construction_01i64_v0_t1_r1_e0_ne0_nw0_se0_sw0_w0",
"construct",
--"deleteware",
"createbob=empire_plus_worker_wall_impulse_add_east",
"createbob=empire_plus_worker_wall_impulse_add_north_east",
"createbob=empire_plus_worker_wall_impulse_add_north_west",
"createbob=empire_plus_worker_wall_impulse_add_south_east",
"createbob=empire_plus_worker_wall_impulse_add_south_west",
"createbob=empire_plus_worker_wall_impulse_add_west",
"playsound=sound_name:mauer_bauen priority:100% allow_multiple",
"animate=working_center duration:5s",
"callobject=construction_completed",
"call=add_wall_connection_to_east skip_this_action_on_failure",
"call=add_wall_connection_to_north_east skip_this_action_on_failure",
"call=add_wall_connection_to_north_west skip_this_action_on_failure",
"call=add_wall_connection_to_south_east skip_this_action_on_failure",
"call=add_wall_connection_to_south_west skip_this_action_on_failure",
"call=add_wall_connection_to_west skip_this_action_on_failure",
"return"

add_wall_connection_to_<richtung> :
"findobject=empire_plus_worker_wall_impulse_add_<richtung> radius:0",
"callworker=construct",
"findobject=attribute:empire_plus_immovable_walls radius:0",
"animate=idle duration:2s",
"callobject=add_east",
"findobject=attribute:empire_plus_immovable_walls_construction radius:0",
"playsound=sound_name:mauer_bauen priority:100% allow_multiple",
"animate=working_<richtung> duration:5s",
"callobject=construction_<richtung>_completed"

Beschreibungen

  • Ich habe das Programm des Mauerbauer Gebäudes unterteilt , da es die Möglichkeit gibt das wenn kein freier Punkt gefunden wurde , es jedoch Mauer Marker Objekte gibt und im Programm zuerst die findspace Aktion ausgeführt wird und erst danach die findobject Aktion , dass dann das Programm abgebrochen wird , da das Ergebnis von findspace negativ ist .
  • Ich habe auch die return=skipped unless object-or-coords Aktion entfernt , da es diese Aktion noch nicht gibt . Dies bedeutet aber nun auch das wenn kein freier Punkt oder kein Marker Objekt gefunden wurde , das dies dann als Fehlschlag in die Gebäude Produktivitätsstatistik eingeht , anstatt als Übersprungen .
  • Nachdem ich mir das Programm des Deicherbauer Gebäudes angeschaut habe , habe ich auch die return=failed unless site has <ware> Aktionen entfernt , da ich die Vermutung habe , das wenn eine Ware die in der consume Aktion hinterlegt ist , nicht im Gebäude vorhanden ist , dass dann die consume Aktion als Fehlschlag ausgeht und das Programm abgebrochen wird und der Fehlschlag mit in die Gebäude Produktivitätsstatistik eingeht .
  • Ich sehe ein mögliches Problem , wenn meine folgende Vermutung zutrifft : Wenn das Gebäude ein Programm des Arbeiters aufruft und es zum Fehlschlag im Arbeiter Programm kommt , dass dann der Fehlschlag des Arbeiter Programms auch an das übergeordnete Gebäude Programm weitergegeben wird , da ja die callworker Aktion einen Fehlschlag hat und somit auch der Abbruch des Gebäude Programms ausgelöst wird . Um das Problem zu umgehen müsste die produce Aktion nach oben , vor die callworker Aktion verschoben werden , um die Vernichtung der Waren auch bei einen potenziellen Fehlschlag im Arbeiter Programm zu verhindern . Ansich habe ich mit dieser Lösung auch keine Probleme .
  • Da das Programm des Gebäudes unterteilt wurde , muss sich im Erfolgsfall das Programm das Mauer Marker Objekte in Mauern umwandelt , sich selbst wiederholen , da der Maurer stets immer zuerst gerichtet Mauern bauen soll , bevor er ungerichtet anfängt zufällig polisitioniert Mauern zu bauen .
  • Möglicherweise funktioniert die construct Aktion des Arbeiters nicht , da keine construct Aktion mehr im Gebäude Programm hinterlegt ist . Deshalb ist eine createware Aktion am Anfang des Arbeiter programms erforderlich , um eine Ware zu definieren . Wenn nicht zu viele Sicherheitsbeschränkungen bei der construct Aktion vorhanden sind , könnte dies so funktionieren . Wenn dies so nicht funktioniert , dann sind weitere Sicherheitsbeschränkungen bei der construct Aktion vorhanden und die construct Aktion des Arbeiters ist stärker mit der construct Aktion des Gebäudes verknüpft . Um dieses Problem zu umgehen ist eine deleteware Aktion , die es noch nicht gibt , erforderlich .
  • Die callobject=construction_completed Aktion ist für den Fall erforderlich das wenn das Mauerbauer Gebäude abgerissen oder zerstört wird , während der Mauerbauer noch an einer Mauer baut , dass dieses Mauer Teil Objekt nicht fertiggestellt wird und sich nach kurzer Zeit wieder in das Ursprungsobjekt zurück transformiert . Gleichberechtigung aber dann auch für die Gegnerseite , wenn der Steinbruch abgerissen oder zerstört wird , während der Steinhauer noch dabei ist , das Mauer Teil Objekt abzureißen , dass dann nach kurzer Zeit das Mauer Teil Objekt sich wieder nach kurzer Zeit in das Ursprungsobjekt zurück transformiert . Es gibt also nun drei technische Mauer Objekt Varianten , einmal das Ursprungsobjekt , dann eine construction Variante und destruction Variante .
  • Ein größeres Problem was sich hier hinauskristallisiert ist das zwar die transformation in Teilen abgesichert werden kann , nicht jedoch alle transformationen als Gesamtes . Um alle transformationen als Gesamtes abzusichern bräuchte es einen Parameter im callworker Programm des Gebäudes , das die Aktionsausgabe der einzelnen Aktionen des aufgerufenen Arbeiter Programmes immer auf positiv setzt , egal was passiert , so das Fehlschläge , wie zum Beispiel der übergeordnete Fehlschlag das Gebäude des Arbeiters ist nicht mehr vorhanden , ignoriert wird bis das aufgerufene Programm sein Ende erreicht hat .
  • Es ist ein skip_this_action_on_failure Parameter erforderlich , falls es kein Mauer Objekt in <richtung> gibt .
  • Beim schreiben fällt mir gerade noch so auf das es nur ein Objekt braucht , was wie auch eine Schiffsbaustelle Baukosten hat . Den die Verbindungen zu den anderen Mauer Objekten zählen bereits zum Mauer Objekt dazu , sind also mit in die Baukosten mit drin . Und das bereits gebaute Mauern nochmal Baukosten haben für Ihre transformation in eine andere Variante , naja das finde ich zu kompliziert . Ich bin mit der aktuellen Variante schon so zufrieden .

Aber jetzt bin ich auf euere Rückmeldungen gespannt

Referenzen

Edited: 2024-09-08, 13:02

Top Quote
Teayo
Avatar
Topic Opener
Joined: 2015-03-09, 22:11
Posts: 220
OS: Windows 11 Home 64-bit
Version: 1.2.1~rc1
Ranking
Widelands-Forum-Junkie
Location: Deutschland
Posted at: 2024-09-08, 16:59

Nachtrag ,
in der Zwischenzeit ist mir eine neue Lösung eingefallen . Daher hier nochmal ein Vergleich bestehender Lösungsansätze .

Methode 1

Methode 1 wurde mal von @Nordfriese vorgeschlagen und funktioniert wie folgt :
- Der Maurer / Steinhauer kommt bei dem Punkt / Marker an und baut dort das erste Mauer Objekt auf .
- Sobald das erste Mauer Objekt aufgebaut ist , wird der Arbeiter mittels der walk=<richtung> Aktion , als Beispiel walk=e , ( siehe auch die Dokumentation zur walk Aktion EN ) zur benachbarten Position bewegt .
- Falls dort ein Mauer Objekt ist , wird dies mittel callobjekt und entsprechender Arbeitsanimation angepasst , so das die graphische Verbindung zwischen den beiden Mauer Objekten entsteht .
- Dies wird für alle Richtungen durchgeführt . Anschließend geht der Maurer zurück zu seinen Mauerbauer Gebäude .

Charakteristiken dieser Methode sind
* serielle Anpassung der Mauer Objekte
* Viele Falls Sonst Bedingungen , die aber nicht verarbeitet werden können , da das Arbeiter Programm beim ersten Fehlschlag immer abgebrochen wird
* Unsicher bei überlagerten Arbeiten

Methode 2

Methode 2 wurde von mir @Teayo bisher lange Zeit verfolgt , entwickelt und funtkioniert wie folgt :
- Der Maurer / Steinhauer kommt bei dem Punkt / Marker an und entsendet Mauer Prüf Impulse zeitgleich in alle sechs Richtungen .
- Wenn keine der benachbarten Mauer Objekte gerade in Anpassung ist , beginnt er das Kern Element des Mauer Objektes aufzubauen .
- Sobald das Kern Element des Mauer Objektes aufgebaut ist , gibt er einen Impuls Objekt den Anpassungsbefehl für das benachbarte Mauer Objekt .
- Anschließend fängt er mit der Arbeitsanimation an , sowie die beiden Mauer Objekte fangen synchron mit Ihrer Anpassung an .
- Dies wird für alle restlichen Richtungen wiederholt , wenn ein Mauer Objekt in der Richtung vorhanden ist .

Charakteristiken dieser Methode sind
* übergeordnete serielle Anpassung der Mauer Objekte und untergeordnete paralelle Anpassung zweier Mauer Objekte
* Es sind Falls Sonst Bedingungen vorhanden , die aber nicht verarbeitet werden können , da das Arbeiter Programm beim ersten Fehlschlag immer abgebrochen wird
* Teilweise vorhandene Unsicherheiten bei überlagerten Arbeiten
+ Dafür aber graphische synchrone Darstellung des Aufbaus einer Verbindung zwischen zwei Mauer Objekten

Methode 3

Methode 3 wurde von mir Teayo , heute konzeptioniert und wurde noch nicht genauer überdacht und kann daher Probleme beinhalten .
Methode 3 funktioniert wie folgt :
- Der Maurer / Steinhauer kommt bei dem Punkt / Marker an und entsendet Mauer Prüf Impulse zeitgleich in alle sechs Richtungen .
- Wenn keine der benachbarten Mauer Objekte gerade in Anpassung ist , gibt der Maurer den Verriegelungsbefehl an alle noch vorhandenen Impulse .
- Nun werden alle benachbarten Mauern und die eigentliche Position beim Maurer gegen überlagerte Bearbeitungen gesichert .
- Anschließend gibt der Maurer allen noch vorhandenen Impulsen einen Planungsbefehl .
- Bei der Hauptposition , wo die Mauer hinzugefügt / entfernt werden soll , werden möglichst schnell und mit sehr kurzen Zeitversatz , alle unsichtbaren technischen Objekte Mauer Planungsmodelle durchgegangen , bis das Mauer Element gefunden wurde , was für diese Position die graphisch richtige Darstellung aller Verbindungen hat .
- Der Maurer gibt nun den Umsetzungsbefehl und alle bis zu 7 Mauer Objekte werden zeitgleich synchron angepasst . Anschließend geht der Maurer zurück zu seinen Mauerbauer Gebäude .

Charakteristiken dieser Methode sind
* paralelle Anpassung der Mauer Objekte
* Nach aktuellen Kenntnisstand sollte es keine Falls Sonst Bedingungen geben .
* Sicherheit bei überlagerten Arbeiten
+ Wie genau das mit den Planungs technischen Objekt abläuft ist noch nicht genauer überdacht worden .
+ Wahrscheinlich deutlich mehr Animations Varianten für die Mauer Objekte .
+ Definitiv eine größere Einschränkung bei der Arbeiter Animation .


Top Quote
hessenfarmer
Avatar
Joined: 2014-12-11, 23:16
Posts: 2743
Ranking
One Elder of Players
Location: Bavaria
Posted at: 2024-09-09, 21:37

Für meine Begriffe sollten für einen Mauerbauer folgende Grundsätze gelten:
1. Aufgrund von Ressourcen und Platzmanagementerwägungen sollten nur Mauern auf Feldern gebaut werden, die durch den Nutzer markiert wurden. (eine prototypische Implementierung unter Nutzung von Haftnotizen hatte ich schon mal ausprobiert)
2. Die einzige Problematik mit einem solchen Ansatz besteht in der grafischen Ausrichtung der Mauerstücke, wenn diese nicht so groß sind wie das Feld und daher automatisch aneinander anschließen. Hier würde im schlectesten Fall ein Lattenzaun aus Mauertücken entstehen.
Zur Lösung dieses grafischen Problems bestehen folgende Schwierigkeiten:
1. Der derzeitge Code lässt es nicht zu die Richtung des nächsten Mauerteils zu ermitteln.
2. Methode 1 hat das Problem, dass durch die Mauerteile selbst die "walk" Aktion fehlschlagen kann.
3. Methoden 2 und 3 sind mit der derzeitigen Codebasis nicht realisierbar.

Daher mein Vorschlag für Methode 4:
1. Jedes der 7 Mauerobjekte (0 bis alle 6 Richtuingen haben einen Anschluß) wird mit den noch zur Verfügung stehenden Anschlußrichtungen registriert. (d.h. alle 6 Richtungen für das Teil ohne Anschluß und keine Richtign für das Teil mit Anschlüssen in alle Richtungen)
2. Wir implementiteren eine direktionale Variante von findobject, d.h. eine Liniensuche statt einer Radiussuche.
3. nach der Fertigstellung eines Mauerteils wird nacheinander mit dem Parameter "on failure=continue" durch einezelne calls in alle Richtungen mit Entfernung nach einem Objekt mit dem jeweils richtigen noch offenen Anschluss gesucht und im Erfolgsfall in den Typ mit geschlossenem Anschluß transformiert.

Das sollte den Aufwand begrenzen und hoffentlich funktionieren.

Aufgrund der begrenzten Verfügbarkeit von Stein auf den meisten Karten ist der spielmechanische Gewinn der Mauerfunktion aus meiner Sicht begrenzt auf Einzelfälle. Daher sollte der Aufwand überschaubar bleiben.


Top Quote
Teayo
Avatar
Topic Opener
Joined: 2015-03-09, 22:11
Posts: 220
OS: Windows 11 Home 64-bit
Version: 1.2.1~rc1
Ranking
Widelands-Forum-Junkie
Location: Deutschland
Posted at: 2024-09-10, 12:30

Aufgrund der begrenzten Verfügbarkeit von Stein auf den meisten Karten ist der spielmechanische Gewinn der Mauerfunktion aus meiner Sicht begrenzt auf Einzelfälle.
Daher sollte der Aufwand überschaubar bleiben.

Ich würde den spielmechanischen Gewinn von Mauern auch ähnlich einschätzen, solange Sie nicht eine gewisse Länge erreicht hat und noch nicht durchgehend ist .
Für das Imperium ist Granit zwar eine begrenzte Ressource , jedoch wird im allgemeinen mehr Marmor als Granit zum bauen benötigt und Granit wird sogar häufiger produziert als Marmor .
Die Idee mit der Mauer kam mir auch deswegen , weil ich in Spielen mit dem Imperium sehr oft einen Granit überschuss im mindestens dreistelligen Bereich und manchmal vierstelligen Bereich habe . Das liegt aber nicht an den oberflächlichen Steinressourcen die von Steinbrüchen abgebaut werden , sondern eher durch die Marmorminen , die Granit ebenfalls produzieren und das nicht wenig . Außerdem sind Mauern ja eine komplett neue Spielmechanik und wer weiß , wenn das mal mit den Mauern und dem Imperium komplett ausgereift ist ,
dann kann man auch mal in ferner Zukunft Mauern auch für die anderen Stämme hinzufügen . Zum Beispiel für die Amazonen die dann da kein Granit benötigen , dafür dann aber Stämme .
Ich habe bereits ein Skizzenbild , sowie ein 3D-Modell für die Mauern der Atlanter . Jedoch hat das 3D-Modell noch keine Oberflächen , geschweige Texturen und das wird auf absehbare Zeit auch nicht dazu kommen .

mit dem Parameter "on failure=continue"

Sehr schön das freut mich . Vorallen das = freut mich , also kann der Parameter auch andere Werte haben als continue .
Also letzendlich reicht mir die Implementierung folgender Funktion :

call=<interner_programm_name> on_failure:<continue|interner_programm_name>

Damit könnte ich nach meiner derzeitigen Einschätzung schon die Methode 3 oder 4 realisieren .
Inzwischen habe ich mich auch komplett von Methode 2 verabschiedet , da Methode 3 einfacher beim skripting ist , jedoch mehr grafik Varianten bei der Animation erfordert .

eine direktionale Variante von findobject , das heißt eine Liniensuche statt einer Radiussuche

Ich verstehe was du damit meinst und wie es funktioniert , auch wenn ich die Anwendung auf der makroskopischen Ebene , mir noch nicht so ganz vorstellen kann .

findobject=<<objekt_name>|attribute:<attribute_name>> <radius:<radius>|direction_<richtung>:<schritte_in_richtung>>
findspace=size:<groesse> <radius:<radius>|direction_<richtung>:<schritte_in_richtung>> <space> <no_notify>

"findobject=attribute:empire_plus_walls direction_east:1",
"callobject=change_east",

Etwa 1 Stunde später nach kurzer Radtour verstehe ich jetzt hessenfarmers Vorschlag und bin absolut begeistert .
Nachtrag : Am nächsten Tag den 10.09.2024 , Post schreiben fortgesetzt :
Einfach nur genial , da es auch das Problem löst , das eine Fehlermeldung erscheint , wenn der Maurer (Arbeiter)
mittels "createbob=empire_plus_worker_wall_impulse_add_east" Aktion versucht ein Impuls (Arbeiter) zu erzeugen .´
Dieses Problem könnte man versuchen zu lösen , indem man "createbob=empire_plus_critter_wall_impulse_add_east" nutzt .
Ich habe jedoch keine Erfahrung mit Tieren (crittern) in Widelands und die Dokumentation EN dazu ist für mich auch nicht aufschlussreicher .
Laut der Dokumentation sollten Tiere auch alle Aktionen nutzen können die auch ein Arbeiter nutzen kann , nur das Tiere im Gegensatz zu Arbeitern ein vorher fest definiertes Hauptprogramm haben .

hessenfarmer's Methode 4 macht sogar meine einstige Anregung an Nordfriese ,
die nun sogar schon mit Widelands 1.2 Release bereits implementiert ist , mit der walk=<e|ne|nw|se|sw|w> Aktion obsolet .
Dokumentation zur Aktion walk EN

Methode 4

Methode 4 wurde zwar von Teayo als Skript ausgearbeitet , ist aber inspiriert von hessenfarmer's Anregung im obrigen Post und wird deswegen hessenfarmer zugeordnet .
Im folgenden das Skript des Maurer Arbeiters :

wall_build_from_object :
"findobject=empire_plus_immovable_wall_place_marker radius:15",
"createware=empire_plus_ware_granite",
"walk=object",

"call=check_walls on_failure:continue",
    "findobject=attribute:empire_plus_walls_construction radius:1",
    "animate=idle duration 5s",
    "findobject=attribute:empire_plus_walls_construction radius:1",
    "animate=idle duration 5s",
    ...
    -- 60s / 5s = 12 Wiederholungen
   "return"

"construct",
    empire_plus_immovable_wall_place_marker [main programm] :
        "construct=idle duration:0s decay_after:60m",
        "transform=empire_plus_immovable_wall_construction_01i64_v0_t1_r1_e0_ne0_nw0_se0_sw0_w0"
            empire_plus_immovable_wall_construction_01i64_v0_t1_r1_e0_ne0_nw0_se0_sw0_w0 [main programm] :
                "animate=idle duration:1s",
                "transform=empire_plus_immovable_wall_place_marker"

"call=start_add_wall_connection_to_east on_failure:continue",
    "findobject=attribute:empire_plus_walls direction_east:1",
    "callobject=construction",
        <mauer_objekt> [construction programm] :
            "transform=empire_plus_immovable_wall_construction_<mauer_objekt_spezifisch>"
                <mauer_construction_objekt> [main programm] :
                    "animate=idle duration:1s",
                    "transform=empire_plus_immovable_wall_place_marker"

    "findobject=attribute:empire_plus_walls_constrution direction_east:1",
    "callobject=add_west",
        <mauer_construction_objekt> [add_west programm] :
            "animate=add_west_fast duration:60s",
            "animate=remove_west_fast duration:60s",
            "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"
    "findobject=attribute:empire_plus_walls_construction radius:0",
    "callobject=change_east"
        <mauer_construction_objekt> [change_east programm] :
            "transform=empire_plus_immovable_wall_construction_<mauer_objekt_spezifisch>"
                "animate=idle duration:1s",
                "transform=empire_plus_immovable_wall_place_marker"

"call=start_add_wall_connection_to_north_east on_failure:continue",
    ...
"call=start_add_wall_connection_to_north_west on_failure:continue",
    ...
"call=start_add_wall_connection_to_south_east on_failure:continue",
    ...
"call=start_add_wall_connection_to_south_west on_failure:continue",
    ...
"call=start_add_wall_connection_to_west on_failure:continue",
    ...

"findobject=attribute:empire_plus_walls_construction radius:0",
"callobject=construction",
    <mauer_construction_objekt> [construction programm] :
        "animate=add_center_fast duration:60s",
        "animate=remove_center_fast duration:60s",
        "transform=empire_plus_immovable_wall_place_marker"

"playsound=sound_name:mauer_bauen priority:100% allow_multiple",
"animate=working duration:60s",

"call=finish_add_wall_connection_to_east on_failure:continue",
    "findobject=attribute:empire_plus_walls_construction direction_east:1",
    "callobject=change_west",
        <mauer_objekt> [change_west programm] :
            "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"

"call=finish_add_wall_connection_to_north_east on_failure:continue",
    ...
"call=finish_add_wall_connection_to_north_west on_failure:continue",
    ...
"call=finish_add_wall_connection_to_south_east on_failure:continue",
    ...
"call=finish_add_wall_connection_to_south_west on_failure:continue",
    ...
"call=finish_add_wall_connection_to_west on_failure:continue",
    ...

"findobject=attribute:empire_plus_walls_construction radius:0",
"callobject=construction_completed",
    <mauer_construction_objekt> [construction_completed programm] :
        "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"

"return"

Daraus ergibt sich das jedes Mauer Objekt folgende Programme haben muss :

empire_plus_immovable_wall_... programme :
main :
    "animate=idle duration:6h",
    --"transform=empire_plus_immovable_wall_ruin_small_<mauer_objekt_spezifisch>"
    "transform=empire_plus_immovable_wall_ruin_small_generic_placeholder"
        <empire_plus_immovable_wall_ruin_small_generic_placeholder> [main programm] :
            "animate=idle duration:6h",
            --"transform=empire_plus_immovable_wall_ruin_none_<mauer_objekt_spezifisch>"
            "transform=empire_plus_immovable_wall_ruin_none_generic_placeholder"
                <empire_plus_immovable_wall_ruin_none_generic_placeholder> [main programm] :
                    "animate=idle"
construction :
    "transform=empire_plus_immovable_wall_construction_<mauer_objekt_spezifisch>"

empire_plus_immovable_wall_construction_... programme :
add_east :
    "animate=add_east_fast duration:60s",
    "animate=remove_east_fast duration:60s",
    "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"
add_north_east :
    ...
add_north_west :
    ...
add_south_east :
    ...
add_south_west :
    ...
add_west :
    ...
change_east :
    "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"
change_north_east :
    "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"
change_north_west :
    "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"
change_south_east :
    "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"
change_south_west :
    "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"
change_west :
    "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"
remove_east :
    "animate=remove_east_slow duration:240s",
    "animate=add_east_slow duration:240s",
    "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"
remove_north_east :
    ...
remove_north_west :
    ...
remove_south_east :
    ...
remove_south_west :
    ...
remove_west :
    ...
construction :
    "animate=add_center_fast duration:60s",
    "animate=remove_center_fast duration:60s",
    "transform=empire_plus_immovable_wall_place_marker"
construction_completed :
    "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"
destruction :
    "animate=remove_center_slow duration:240s",
    "animate=add_center_slow duration:240s",
    "transform=empire_plus_immovable_wall_<mauer_objekt_spezifisch>"
destruction_completed :
    "removeobject"

Zusammenfassung was implementiert werden muss

Objekttyp Aktion Parameter Werte Kommentar
Gebäude
Arbeiter
Unbewegliche Objekte
call <interner_programm_name> Laut Dokumentation gibt es diese Aktion derzeit nur für Gebäude .
Autogen Tribes Productionsite Programs Dokumentation Aktion call EN

Sollte auch für Arbeiter , Tiere und Unbewegliche Objekte hinzugefügt werden .
Gebäude
Arbeiter
Unbewegliche Objekte
call on_failure Ein neuer Parameter der definiert wie das Programm fortgesetzt wird ,
wenn die call Aktion vom Programm eine Fehlschlag Rückgabe vom aufgerufenen Programm erhält .
Gebäude
Arbeiter
Unbewegliche Objekte
call on_failure: continue Wenn es zu einen Fehlschlag innerhalb des aufgerufenen internen Programmes kommt , dann wird der Fehlschlag nicht an das übergeordnete Programm weitergegeben , dass das untergeordnete Programm mit dem Fehlschlag aufgerufen hat .
Das übergeordnete Programm setzt seinen Aktions Ablauf normal fort .
Gebäude
Arbeiter
Unbewegliche Objekte
call on_failure: cancel
(default value)
Wenn der Parameter on_failure bei der call Aktion nicht angegeben wird ,
dann wird der Wert cancel standardmäßig für den Parameter on_failure angenommen .
Wenn das aufgerufene Programm einen Fehlschlag als Rückgabe ausgibt , so wird der Fehlschlag auch an das übergeordnete Programm weitergegeben , was das untergeordnete Programm mit dem Fehlschlag , aufgerufen hat .
Auch das übergeordnete Programm wird abgebrochen , es werden keine weiteren Aktionen mehr vom abgebrochenen Programm aufgerufen und es wird das main Programm aufgerufen .
Arbeiter
Tiere
findobject direction_east:
direction_north_east:
direction_north_west:
direction_south_east:
direction_south_west:
direction_west:
<Ganzzahl integer>
0 bis 255
Ein neuer Parameter der statt einer Radius suche in alle Richtungen ,
nur in eine mit dem Parameter definierte Richtung nach Objekten sucht .

Wenn ein Objekt gefunden wurde , muss dieses bei der Hindernisprüfung trotzdem mit dem im Parameter angegebenen Schritten erreichbar sein .
Arbeiter
Tiere
findspace direction_east:
direction_north_east:
direction_north_west:
direction_south_east:
direction_south_west:
direction_west:
<Ganzzahl integer>
0 bis 255
Ein neuer Parameter der statt einer Radius suche in alle Richtungen ,
nur in eine mit dem Parameter definierte Richtung nach einen Punkt sucht .

Wenn ein Punkt gefunden wurde , muss dieser bei der Hindernisprüfung trotzdem mit dem im Parameter angegebenen Schritten erreichbar sein .
Arbeiter
Tiere
walk ignore: object_size
terrain_walkable
any
Ein neuer Parameter der die Hindernisprüfung teilweise oder komplett überspringt .

Standardmäßig können Punkte an deren Position sich ein Objekt befindet , was die Eigenschaft :
size:medium , size:big , size:port oder size:mine besitzt ,
nicht vom Objekt was die walk Aktion ausführt , betreten werden .

Standardmäßig können Punkte die die Eigenschaft unbegehbar oder unerreichbar besitzen ,
nicht vom Objekt was die walk Aktion ausführt , betreten werden .

Technische Objekte , Ambient Objekte ---> Nebel , Wolken , Hafenarbeiter für Pier Anlegestege

Bild - Übersicht aller Mauer Varianten

Edited: 2024-09-10, 12:33

Attachment:
alle_mauern_uebersicht_klein.jpg

Top Quote