Latest Posts

Topic: Mauern Skript

Teayo
Avatar
Topic Opener
Joined: 2015-03-09, 21:11
Posts: 171
OS: Windows 11 Home 64-bit
Version: 1.2 from Juni (06) 2023
Ranking
At home in WL-forums
Location: Deutschland
Posted at: 2024-09-05, 15: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, 15:47

Das Imperium schlägt zurück ! TY

Top Quote
Nordfriese
Avatar
Joined: 2017-01-17, 17:07
Posts: 2002
OS: Debian Testing
Version: Latest master
Ranking
One Elder of Players
Location: 0x55555d3a34c0
Posted at: 2024-09-05, 16: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, 16:19

Top Quote
Teayo
Avatar
Topic Opener
Joined: 2015-03-09, 21:11
Posts: 171
OS: Windows 11 Home 64-bit
Version: 1.2 from Juni (06) 2023
Ranking
At home in WL-forums
Location: Deutschland
Posted at: 2024-09-05, 21: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 .


Das Imperium schlägt zurück ! TY

Top Quote
hessenfarmer
Avatar
Joined: 2014-12-11, 22:16
Posts: 2699
Ranking
One Elder of Players
Location: Bavaria
Posted at: 2024-09-05, 22: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, 21:11
Posts: 171
OS: Windows 11 Home 64-bit
Version: 1.2 from Juni (06) 2023
Ranking
At home in WL-forums
Location: Deutschland
Posted at: 2024-09-05, 23: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-05, 23:26

Das Imperium schlägt zurück ! TY

Top Quote
hessenfarmer
Avatar
Joined: 2014-12-11, 22:16
Posts: 2699
Ranking
One Elder of Players
Location: Bavaria
Posted at: 2024-09-06, 10: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