The International Simutrans Forum

Development => Extension Requests => Topic started by: zhaop on July 03, 2015, 04:46:16 PM

Title: Build ways (and more) from API
Post by: zhaop on July 03, 2015, 04:46:16 PM
I'm thinking of scripting AIs using the squirrel API so that they can play the game automatically.

Currently, the squirrel API is mostly a read-only window into the game, in the sense that not much of the game can be modified by it, except for creating labels and removing objects from tiles.

How hard would it be to implement API functions that could "play the game", build roads and bridges, construct depots and stations, and maybe even use some native simutrans functions (e.g. pathfinding/routing)?
Title: Re: Build ways (and more) from API
Post by: zhaop on July 10, 2015, 12:56:01 PM
I thought I'd give this a try. This is my first time diving into Simutrans' source (hooray), and a couple of segfaults later, I made this squirrel function, which builds a road/railway/anything (default_param can be "road_070", or "2" for railways, etc) from pos to pos2, for player pl.
static void way_x.build(string default_param, coord pos, coord pos2, player_x pl)

It turns out we can have some fun with this! Starting with an almost empty flat map, here's what happens when I used way_x.build() to pave a hundred roads, railways, canals and monorails from one random coordinate to another, each in their own quadrant. It seems each quadrant has its own style of connecting roads together.

(http://i572.photobucket.com/albums/ss162/eater44/quadrants.png~original)


And here's when we put down monorails, then canals, then railways, then roads, on the entire map. (Looks almost like an actual transport network thing.)

(http://i572.photobucket.com/albums/ss162/eater44/whole%20map.png~original)


Now I realize that the API is currently limited to "read-only" functionality (i.e. no way to change the game state), so I wonder if it was an intentional decision to keep the API lightweight, and if there's any sense to continue working on extending the API? :)
Title: Re: Build ways (and more) from API
Post by: Ters on July 10, 2015, 02:13:25 PM
Recently, Simutrans seems to have evolved through random contributions by individual developers. I don't think there is any decision on the ultimate goal of the scription functionality, except to support scenarios (which likely would eventually need to modify something somehow). Development just stopped at some point for whatever reason. There have been many suggestion for things that could be possible through scripting, but nobody ever started implementing something. (Major contributions generally come from those who desire a feature themselves.)

There seems to be low activity from those who can commit changes to Simutrans recently. This might make it somewhat difficult to get feedback on whether your changes follow general guidelines for Simutrans as a whole. Some language and library features might not be supported on all target platforms for instance.

(I know nothing about Simutrans' scripting abilities. Llow level stuff is where I've mostly contributed.)
Title: Re: Build ways (and more) from API
Post by: prissi on July 10, 2015, 11:11:32 PM
The ultimative goal of scripting was rather to have AI as scripts (like OpenTTD).

As such way building by scripting is desirable. It should be done best sending coomand via the interface to make it network safe. However, it is easy to do so, and any further progress on this is highly welcome.
Title: Re: Build ways (and more) from API
Post by: zhaop on July 11, 2015, 01:59:48 PM
Thank you Ters and prissi, I feel very much encouraged to move forward with this!

I'm currently working on allowing the API use all of the "button tools" in the top toolbar. My implementation calls init and work on the general tools (for instance, tool_build_way_t::work). Is this what prissi means by "sending commands via the interface"?

In fact for now, I think I will only define the following 2 squirrel functions using C. These are inspired by similar functions in player/ai.cc:
static bool world::init_general_tool(player_x pl, int tool, string param)
static bool world::call_general_tool(player_x pl, int tool, coord pos, string param)


The rest of the higher-level functions like build_way, build_depot, etc could then be defined using only squirrel code that call init_general_tool and call_general_tool. For example:
// bool build_way(player_x pl, string param, coord pos1, coord pos2)
function build_way(pl, param, pos1, pos2) {
   return world.init_general_tool(pl, general_tools.build_way, param) && world.call_general_tool(pl, general_tools.build_way, pos1, param) && world.call_general_tool(pl, general_tools.build_way, pos2, param)
}


This way, most development will be in Squirrel instead of C so there's less compiling right away (at the expense of some runtime performance). Maybe once the way forward is clear could some of the more useful API functions be moved to C for better performance. What do you all think?

EDIT: Just discovered and read over the thread where scripts all started (http://forum.simutrans.com/index.php?topic=8947.0;all)! :D
Title: Re: Build ways (and more) from API
Post by: Ters on July 11, 2015, 06:41:18 PM
There is a rule in development in general is to make it work first, and make it work fast later if needed. Within some reasonable bounds.
Title: Re: Build ways (and more) from API
Post by: prissi on July 11, 2015, 10:17:58 PM
I think doing the actual implementation in squirrel is a good idea; for instance some commands (e.g. in the depot) are using additionally subcommands. Any changes there as well as extensions would be only needed to be extended in the squirrel interface.

The waybuilder may be a sensible extension, for the terraforming etc, as well as use the exiting route to avoid a station on the closer side which leads to a connection going 270 degree around as the only access option. See at_::create_simpe_rail_transport. Also building way with tunnel and bridges (though these may be now rarely build built with the new ladscape code) might be an issue.

The other function, you should rather implement in C++, is the location finder (like "ai_t::suche_platz()"). These are very time consuming tasks, and hence really more suited for native code. Maybe just reuse ai_t::suche_platz().