Latest Posts

Topic: suggestions for scripting api

aDiscoverer
Avatar
Topic Opener
Joined: 2022-10-29, 13:23
Posts: 19
Ranking
Pry about Widelands
Posted at: 2023-06-22, 17:53

Some suggestions to make scripting simpler of more powerful.

check if map object is removed

How can I check if a mapobject (building, soldier, ...) still exists? Using any attribute after it disappeared raises an error "ConstructionSite no longer exists!".

I propose aMapObject:exists() or aMapObject.exists

my workaround for immovables is using the (main) field:

fx = anImmovable.flags[1]
sleep(123)
if fx.immovable ~= anImovable then
    break -- or whatever
end
anImovable.xxx

allow evicting a worker from by script

I propose to add ps:evict(worker_xx) to productionsite. I am unsure how to identify the workers, probably as bob. The function would return false when it failed (because of a worker not belonging to the building or ...)

Use case: I try to write a script assisting the ai player with poor hamlet. A worker needs to change between lumber jack and wood hardener.

add possibility to detect human players in multiplayer game

How can I find out if a player is human-controlled in a multiplayer game? I can easily find out which player is the human of this game instance (with wl.Game().interactive_player). But not the players playing on the other computers. The best I found is checking if player.name is Computer %d with %d being the player number. There are several drawbacks. (1) A human could enter his name like this. (2) The name is translated by the host. When the netclient runs with a different language, it will likely not match.

note to case (1): The button to join is disabled when the human chooses a name with a space in it. But with a double click on the game, joining continues anyway. (Bug, using widelands 1.1) If the map is chosen before, the name is occupied by the (potential) ai player and the human gets 1 attached to his name. If the map is not yet selected or changed (to one with more players), the human has his name already. In case both players end up in the game and should have the same name, the computer gets a different number. (one higher/lower).

allow win conditions to have a config dialogue

Show a button for those win conditions which allow a config dialogue. see more details in forum post ..92

allow to adapt the build costs of workers

the-x-mod adapts build costs of buildings. Adapting costs for workers and soldiers could be interesting as well.

wl_descr:modify_unit("worker", lumberjack_name, "buildcost", "set", new_costs)

allow to add an additional ai player to any map

To make artifacts which are defended. more details in forum post ..93

include(xxx) returns the scripts return value

I found out normal lua supports require(xxx) which returns the return value of the script and only includes the script if it is not yet imported.
Maybe somebody could teach include() this two things. Or at least the return value.

The return value would make reusing of start conditions simpler. ( forum post ..93)
And it would allow variables to be local and only be shared with those really needing them. (Kind of modules in lua)


Thank you for the game. Looks like I like it face-smile.png

Edited: 2023-06-23, 14:20

Top Quote
Nordfriese
Avatar
Joined: 2017-01-17, 18:07
Posts: 2051
OS: Debian Testing
Version: Latest master
Ranking
One Elder of Players
Location: 0x55555d3a34c0
Posted at: 2023-07-01, 19:47

These are some good suggestions, I opened a PR to add for v1.2:

  • evict() as a function of a Worker
  • exists as a property of a MapObject
  • "buildcost" "set" <name> <amount> and "buildcost" "remove" <name> for modify_unit "worker"

add possibility to detect human players in multiplayer game

Sadly not possible – from a client's perspective there is no way to tell whether any given player is controlled by AI or humans. Only the host has that information. But control of a player can even be shared across multiple players and potentially an AI as well.

allow win conditions to have a config dialogue

For this to work, the win condition would have to specify what kind of parameters it has and how they should be represented (data type, widget type, min/max/initial values), and the UI would have to present all that to the user… that's doable but would be pretty involved to implement.

allow to add an additional ai player to any map

Unfortunately that's not doable at all face-sad.png

include(xxx) returns the scripts return value

That's not actually that hard but would require some tricky fiddling with the lua_State API. That could be a Good First Issue for anyone who wants to delve deeper into the C++/Lua interfacing logic.
The function is implemented as L_include in lua_globals.cc.


Top Quote
aDiscoverer
Avatar
Topic Opener
Joined: 2022-10-29, 13:23
Posts: 19
Ranking
Pry about Widelands
Posted at: 2023-07-03, 18:14

Nordfriese wrote:

These are some good suggestions, I opened a PR to add for v1.2:

  • evict() as a function of a Worker
  • exists as a property of a MapObject
  • "buildcost" "set" <name> <amount> and "buildcost" "remove" <name> for modify_unit "worker"

Great, thank you very much indeed!

add possibility to detect human players in multiplayer game

Sadly not possible – from a client's perspective there is no way to tell whether any given player is controlled by AI or humans. Only the host has that information. But control of a player can even be shared across multiple players and potentially an AI as well.

Sad. Some more details later in a separate answer.

allow win conditions to have a config dialogue

For this to work, the win condition would have to specify what kind of parameters it has and how they should be represented (data type, widget type, min/max/initial values), and the UI would have to present all that to the user… that's doable but would be pretty involved to implement.

My suggestions in the forum post #..92 was to support integers only. I agree to max, min and initial. I see no need for any other data types and widget type. (It might pop up later of course for ideas I can not imagine.)

r = {
    allow_peaceful = true,
    config = {
        conquer = {
            label = _"percent to conquer",
            min = 30,
            max = 100,
            default = 50,
        },
        keep = {
            label = _"minutes to keep territory",
            default = 20,
            -- min is 0 normally, max is BIG normally
        }
    }
    ...

To support this for multiplayer as well, it would even have to be transferred to the netclients. It could be for single player only.
But I agree it would be involving already to implement this (integer, singleplayer).

allow to add an additional ai player to any map

Unfortunately that's not doable at all face-sad.png

I can imagine this is totally against the way widelands works. I forget it.

include(xxx) returns the scripts return value

That's not actually that hard but would require some tricky fiddling with the lua_State API. That could be a Good First Issue for anyone who wants to delve deeper into the C++/Lua interfacing logic.
The function is implemented as L_include in lua_globals.cc.

Good first issue but tricky fiddling? Sounds a bit too challenging. I probably stay with scripting -\(")/-


Top Quote
aDiscoverer
Avatar
Topic Opener
Joined: 2022-10-29, 13:23
Posts: 19
Ranking
Pry about Widelands
Posted at: 2023-07-05, 15:08

allow win conditions to have a config dialogue

For this to work, the win condition would have to specify what kind of parameters it has and how they should be represented (data type, widget type, min/max/initial values), and the UI would have to present all that to the user… that's doable but would be pretty involved to implement.

My suggestions in the forum post #..92 was to support integers only. I agree to max, min and initial. I see no need for any other data types and widget type. (It might pop up later of course for ideas I can not imagine.) r = { allow_peaceful = true, config = { conquer = { label = _"percent to conquer", min = 30, max = 100, default = 50, }, ...

To support this for multiplayer as well, it would even have to be transferred to the netclients. It could be for single player only.
But I agree it would be involving already to implement this (integer, singleplayer).

With pr 5933 - Lua UI api extension maybe the win condition just needs to declare a function like config_dialogue() and a button is enabled in the game dialogue if the function is defined. I did not yet look into it and see if returning values is easy.
I suppose config_dialogue() returns the values in a table {p_conquer = 50, m_keep = 20} and this can be accessed as RO property of wl.Game() (like win_condition_duration) or as argument to init(...) and func(...).
A first step of supporting this only in single player mode could make sense.


Top Quote
aDiscoverer
Avatar
Topic Opener
Joined: 2022-10-29, 13:23
Posts: 19
Ranking
Pry about Widelands
Posted at: 2023-07-06, 00:44

add possibility to detect human players in multiplayer game

Sadly not possible – from a client's perspective there is no way to tell whether any given player is controlled by AI or humans. Only the host has that information. But control of a player can even be shared across multiple players and potentially an AI as well.

Sad. Some more details later in a separate answer.

Some more details

I understand that multiple humans can control a player. And with playerMe:switchplayer(3) a human could share control with an ai.

Short wish: could get_ai() (from src/logic/player.cc) be accessible as RO property of a player in lua? (totally unsure about the name: ai/ai_type/...) I should be able to write the code for this.

Longer, why I wish it:

Imagine I want to disable some buildings for all AI players by script (until they have built something specific). Detecting the ai players is no problem for single player as I can identify the human player by wl.Game().interactive_player. In a multiplayer game, wl.Game().interactive_player only shows the human player of this machine (for nethost and netclient). In case I use this information in the script, I will get a desync because I use different players on the machines. To not get a desync, it is important that the script on both machines selects the same players. (And I do not want to limit the human players, they shall think themselves.)

The nethost knows what players are not human controlled. But this is only published to lua by player name (on nethost and netclient). The name of a user might interfer. (About problems of its localisation #5991) Could something more helpful be available to lua like playerX.ai_type (or another property name)?

I am aware that this information does not exclude that additionally a human controls this player. But only in edge cases, which I do not care about. I am aware that a player controlled by a human will be controlled by an AI after the connection to the human player is lost. I ignore this.


Top Quote
aDiscoverer
Avatar
Topic Opener
Joined: 2022-10-29, 13:23
Posts: 19
Ranking
Pry about Widelands
Posted at: 2023-07-08, 00:45

aDiscoverer wrote:

add possibility to detect human players in multiplayer game

Sadly not possible – from a client's perspective there is no way to tell whether any given player is controlled by AI or humans. Only the host has that information. But control of a player can even be shared across multiple players and potentially an AI as well.

Ah, now I undestand your statement. src/ai/defaultai.h writes that only the host runs the ai code and sends the player commands to the clients. So get_ai() (from src/logic/player.cc) is likely empty on netclients. But in src/network/gameclient.cc player.ai is received and saved. It might be available on a netclient ... How can I check this without having a debug build and without compiling?


Top Quote
aDiscoverer
Avatar
Topic Opener
Joined: 2022-10-29, 13:23
Posts: 19
Ranking
Pry about Widelands
Posted at: 2023-10-11, 10:43

teresa.harris wrote:

I would introduce a method like aMapObject:exists() or aMapObject.exists to check if a map object (e.g., a building, soldier, or construction site) still exists. This would prevent errors when accessing attributes of objects that have disappeared.

mapObject.exists is introduced in the code already, it will be available for version 1.2:

https://www.widelands.org/documentation/autogen_wl_map/#wl.map.MapObject.exists

It was introduced in commit 10b692a0 as announced in a post above

Edited: 2023-10-11, 10:46

Top Quote
aDiscoverer
Avatar
Topic Opener
Joined: 2022-10-29, 13:23
Posts: 19
Ranking
Pry about Widelands
Posted at: 2023-10-11, 11:28

aDiscoverer wrote:

aDiscoverer wrote:

add possibility to detect human players in multiplayer game

Sadly not possible – from a client's perspective there is no way to tell whether any given player is controlled by AI or humans. Only the host has that information. But control of a player can even be shared across multiple players and potentially an AI as well.

Ah, now I undestand your statement. src/ai/defaultai.h writes that only the host runs the ai code and sends the player commands to the clients. So get_ai() (from src/logic/player.cc) is likely empty on netclients. But in src/network/gameclient.cc player.ai is received and saved. It might be available on a netclient ... How can I check this without having a debug build and without compiling?

Status, there is a pull request for player.ai_type on https://github.com/widelands/widelands/pull/6001 (same as https://codeberg.org/wl/widelands/pulls/4412)


Top Quote