News:

Simutrans Wiki Manual
The official on-line manual for Simutrans. Read and contribute.

Growth scenario

Started by isidoro, January 07, 2014, 01:24:54 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

isidoro

I would like to try the scenario feature of ST.  My idea is quite different from the examples given and I don't know if it is ever possible.  The public service would play an important role and make strategic decisions on where to build new industries/attractions and make cities grow:

       
  • I'd like to use pak128.Britain and start from 1750
  • The goal is to reach a certain global population as soon as possible
  • At the beginning the map is empty
  • The public service can found new cities at will
  • Each city has building points.  Each building/factory/attraction belonging to the city subtracts building points.  A city can earn building points when it has any pak.128Britain's Building yards and they consume bricks, clay, stone, ...
  • The public service can build new industries for a city: 1) if they are available in that date, 2) if it has the relevant building points (that depends on the type on industry and the intended max production for it), 3) if the max production of the new industry is not too high for the type of industry/date and 4) if, in the case that the new industry produces certain raw materials (e.g. coal, stone, clay, oil), the place has that raw material available
  • The public service can build new attractions/buildings for a city provided it has enough building points (those depend on the pass/mail level of the new building
  • At the beginning of each month, the population of a city can grow +100 or shrink -100 (up to a limit), depending on how well its people is served with food and clothes.  For each inhabitant and month, the city needs a level of protein (fish, meat or milk), carbohydrates (flour or milk), fruit+vegetables, and clothes.  The consumption of fishmongers, butchers, etc. belonging to that city is measured and if all levels are fulfilled and "allow city growth" is on, the city grows.  If any of the levels is below, the city shrinks
  • The previous levels can be lower if the city is provided in this order with enough amount of: first, furniture, then energy (coal yard, not power stations for this), then medicines.  This way, there are fewer deaths.
  • Alcohol, hardware and china consumption only generates cash.
  • I would like to include a rule regarding oil, petrol stations and car dealerships (something like you can't buy certain lorries/cars if the city is not provided with enough petrol), but I guess that is not possible...
  • I would also like to include certain rules about consuming industries: a dairy will provide protein levels for a city not only if it consumes milk but also if provided with passengers (but I guess that this is difficult)...
  • Power stations and electricity follow the usual rules, although the rules for building them are the same as for any other industry.
What do yo think?

About the technical issues:

       
  • I've seen that the squirrel function start() is called at the beginning of the scenario.  Is there another function that is called at the beginning of each month and after all industry/city statistics are computed?
  • I've also seen that certain buttons of the gui can be turned on and off.  Moreover, when the player builds something, it can be prevented with a message or allowed.  Does the latter apply to the public service as well?  Does the relevant function receive the data of the item that the player wants to build (for instance, the production/consumption of a new factory)?
  • Any other pitfalls that make this impossible?

Dwachs

Quote from: isidoro on January 07, 2014, 01:24:54 AM
What do yo think?
This is a great idea! I would really like to see this taking off!

Now to answer your questions:
Quote
I would also like to include certain rules about consuming industries: a dairy will provide protein levels for a city not only if it consumes milk but also if provided with passengers (but I guess that this is difficult)...
The script can query most of the in-game statistics, among them consumption and passenger support of factories, http://dwachs.github.io/simutrans-sqapi-doc/classfactory__x.html
Quote

       
  • I've seen that the squirrel function start() is called at the beginning of the scenario.  Is there another function that is called at the beginning of each month and after all industry/city statistics are computed?
Not yet, can be added with ease.
Quote

       
  • I've also seen that certain buttons of the gui can be turned on and off.  Moreover, when the player builds something, it can be prevented with a message or allowed.  Does the latter apply to the public service as well?  Does the relevant function receive the data of the item that the player wants to build (for instance, the production/consumption of a new factory)?
The checks happen on the script side, see http://dwachs.github.io/simutrans-sqapi-doc/classrules.html and http://dwachs.github.io/simutrans-sqapi-doc/api__skeleton_8cc.html#a67f167f50ac44e2affeec9b47fd76093 . This means, the script can be adjusted to allow everything for public player but restricting the human players.

These methods cannot check for the precise item (which type of road, building etc).
Quote

       
  • Any other pitfalls that make this impossible?
Scripts cannot built anything yet. Which should not restrict you now in planning your scenario. Any serious effort on  scenarios also is a *big* motivation to work on the scripting interface. Adding functions to build factories and attractions at/near particular spots is not that difficult, the functionality is in the code already, only the interface is missing.
Parsley, sage, rosemary, and maggikraut.

isidoro

Thanks, Dwachs.

I've working on it a bit, and it is quite nice and I think that it opens a lot of possibilities for not-so-expert programmers to adapt the game to their preferences.

The main limitation I can see so far for my scenario to come true is that of knowing in advance the properties of the "thing" the player wants to build.  Apart from that, the feature would also be interesting for preventing to build certain factories away from rivers or similar questions posed in other threads that would not need to be hard-coded in the main exe, but could be solved in the scripting side.

But let's see where I can get...

At the moment, there seems to be a bug in file script/api_param.cc, lines 305 and 306:

                        i = param<sint16>::get(vm, -1);
                        sq_pop(vm, 1);


Squirrel kept on giving me errors whenever I asked a factory about the consumed amount of an input product.  If I deleted those two lines, everything seemed to go fine.  But I don't know for sure if it is a bug since I don't know anything about the Squirrel interface...


Dwachs

This is indeed a bug! Thanks for spotting this.

In which ways would you like to limit payers to build certain things? You can password-protect public player, forbid building of industries, for instance.
Parsley, sage, rosemary, and maggikraut.

isidoro

You're welcome.

I'd like to be able to be more selective: whenever the (public) player builds an industry, attraction, etc. now I can know the coordinates and general type of building (industry, attraction,...) and can allow or deny it.  What would be great is to have some extra information about the specific kind of industry, attraction, etc. and its max. production the (public) player intends to build.  That way, I can selectively allow or deny certain kinds of industries.  Or some of them near others, or near certain places, or in some periods (for example in a historical war)...

This way it is not necessary for the scripts to be able to build things themselves, but suffices to allow/deny the player's initiative based on certain rules.


prissi

While implementation is possible, such a behaviour is extremely frustrating. Do not build here but five tile to the left ... Then I would rather go for skripted building. Actually, the code for this is almost there (the command system was build with also this in mind, even though no scripting existed back then). In principle the type of command, the number of the command and the command string (which can be obtianed also from -log 3 messages) are the only input parameter needed.

isidoro

In the scenario I proposed I need to selectively allow/deny certain buildings due to their size, for instance.  For example, a city may have enough materials to build a church, but not so many to build a cathedral.  A message like: "you don't have enough materials to build this building" would appear whenever the (public) player wants to build the cathedral in that city.

Up to know, the progress is quite straight forward although I have to play the game while designing to see the effects and it takes time.  BTW, thanks Dwachs for implementing the new month and new year callbacks.

I have encountered two problems so far: 1) when loading a game with an scenario back, there appears an error, something about a userdefinedstring problem.  I guess it has to do with a wrong use of the persistent table. 2) I don't know why, today it didn't allow me to switch players back and forth again.  I had to temporarily use the brute-force...  :police:

Dwachs

Your proposal sounds like you want to limit only the public player to build attractions, factories etc. This can certainly be done. The hooks have to be placed in different routines, as cities build things directly without using the tool-framework (simwerkz.cc).

Quote from: isidoro on January 09, 2014, 12:10:05 AM
I have encountered two problems so far: 1) when loading a game with an scenario back, there appears an error, something about a userdefinedstring problem.  I guess it has to do with a wrong use of the persistent table. 2) I don't know why, today it didn't allow me to switch players back and forth again.  I had to temporarily use the brute-force...  :police:
1) If you upload script + savegame I can help with debugging. There is still the chance that something is wrong in the code.

2) Switching players is disallowed by default, see lines 34-51 in script/scenario_base.nut
Parsley, sage, rosemary, and maggikraut.

isidoro

Not quite.  What I intend to do is that the player, switching to the public service and using its map editing tools, is the one building the factories and linking them.  And that the script be able to control what is allowed and what is denied and why.

This way, the player has to develop not only a good and profitable traffic network, but alto take strategic decisions about how to develop the map (where to place factories, new cities and attractions).

Quote from: Dwachs on January 09, 2014, 06:50:41 AM
1) If you upload script + savegame I can help with debugging. There is still the chance that something is wrong in the code.

At the moment, I'm focused in seeing what is available and what can be done.  When the script has something more mature to show, I'll upload it and try to deal with those other problems.

BTW, is there a way I can show text in colors (specially red and green) in the Progress tab?


Dwachs

Quote from: isidoro on January 10, 2014, 12:19:01 AM
BTW, is there a way I can show text in colors (specially red and green) in the Progress tab?
You can use all the pseudo-html tags simutrans uses to display in-game help text:
http://dwachs.github.io/simutrans-sqapi-doc/api__skeleton_8cc.html#a706b5bd21f80fc116a158dc964a5cfed
Parsley, sage, rosemary, and maggikraut.

Dwachs

Sorry for double-post:

Regarding debugging: I am curious how you managed to find the bug in api_param.cc above, I could not trigger an error with my nut scripts.

Quote from: isidoro on January 10, 2014, 12:19:01 AM
Not quite.  What I intend to do is that the player, switching to the public service and using its map editing tools, is the one building the factories and linking them.  And that the script be able to control what is allowed and what is denied and why.
I see. This would require to map parts of the werkzeug_t class hierarchy to squirrel classes. Quite some bit of work. It is possible. And may pay-off in the long-run (as enabling scripting for AI is still a long-term goal).
Parsley, sage, rosemary, and maggikraut.

prissi

To built something a squirrel script would only need three functions for general tools, one click tools and dialoge tools, and then a position and a string. That should be quite easy and straight forward. Or did I misunderstood something?

However, to allow or deny something, almost any tool needs to be filtered by squirrel. That seems indeed like an effort.

isidoro

@Dwachs: thanks for the tip.  Now I have red to mark a deficit.
Quote from: Dwachs on January 10, 2014, 09:10:53 AM
Regarding debugging: I am curious how you managed to find the bug in api_param.cc above, I could not trigger an error with my nut scripts.

I am trying first to get the maximum information available.  I made a loop to show each factory information.  Something like: theFactory.input.["bricks"].get_consumed()[0].  I run the script and got the error.  Looked for the possible places where the error could come and set a breakpoint there and looked at the variables stepping line by line.  Before those two lines, the variable was correct.  After them, incorrect.  I tried and erased the lines and everything seemed to work alright (checked with the information given in the dialogue of factory information).

Quote
I see. This would require to map parts of the werkzeug_t class hierarchy to squirrel classes. Quite some bit of work. It is possible. And may pay-off in the long-run (as enabling scripting for AI is still a long-term goal).

The ability of a script to build something may be interesting in general, but not so for my script (as far as I understand it).

Now I have more or less all the information I need from the objects.  I know now how many building points and food and clothes a given city has.  Now I need to restrict what the player can build with the public player tool.  I can see two options:

       
  • If a fourth parameter were added to is_work_allowed_here() telling the description of the object the player is trying to build (building_desc_x or similar), I could easily restrict that.  But if complicated, only the name of the object in the pak (e.g. BuildingYard1750) would suffice, since that information is static and can be included in the script.  If apart from that I could also have the production value input by the player in the factory builder dialog, that would be great.
  • The other possibility I'm exploring is more time consuming, error prone an inexact: allow to build anything in that city while the building points are positive.  But I have to cycle all the time tile by tile around the city accounting for how many buildings are already built.  I've tried and in fact the CPU time goes up.  Besides, since the player has one building he can build with no immediate cost, he can cheat and build a big stadium the first time...  Nevertheless, I think I'll keep on trying this possibility.
I'll keep you informed of my progress here and eventually show the code, when there is something worth to be shown.


isidoro

I've nearly achieved the first part of the scenario:  building construction limitation.  However, I've stumped into a small problem: attractions.

In the squirrel's API, there are factory_list_x and the corresponding factory_x that allows you to easily iterate over all factories.  But there is not an attraction_list_x and the corresponding attraction_x to do the same.  Although I have tried to iterate over all tiles in the map and get the information, the thing gets complicated with multi-tile attractions.  Would it be possible to have that information available directly from the game engine, à la factory style?


Dwachs

It is possible to export a list of all build attractions. The list would contain all tiles of an attraction individually (instances of building_x). This is due to the fact that simutrans internally has no abstraction for multi-tile buildings. All tiles of buildings are treated individually, each tile knows that is is a sub-tile of a multi-tile building. But the is no multi-tile building has no representation itself.

Edit: I guess you would then need a function to decide whether two given building tiles actually belong to the same multi-tile building?
Parsley, sage, rosemary, and maggikraut.

isidoro

Not really.  It is better to have the proper list attraction_list_x and the proper object attraction_x.  Just the same that happens with factories.  And I guess that that behavior is inside the engine since if you press the lists button and, then, list of tourist destinations, there appears one entry for each attraction.

Moreover, if you click on any of the tiles of an attraction with the information tool, the window that appears have the same coordinates no matter what tile of the attraction you press.  This behavior is just like with factories.

To know if two building tiles belong to the same attraction, in this case, I could do the same I do with factories:  ask for the get_pos() method of factory_x and compare the values.


Dwachs

Here is a patch.

Usage:

local attraction_list = get_attraction_list()
foreach(att in attraction_list ) {
...
}

Is this what you wanted?
Parsley, sage, rosemary, and maggikraut.

isidoro

Thank you indeed!  It works like charm.

Only to get a taste of the WIP, I attach the present state.  You need a nightly of Pak128.Britain and a savegame named "test.sve".  Better if it has some Building Yards well provided.  You can see the building materials accumulate in the relevant city.

Comments and guidelines are welcome.


Yona-TYT


Big ..! the first scenario for pak128.Britain  ;D


Just have time I test.. :thumbsup:

isidoro

In fact, it is just work in progress.  Nothing really playable yet.  I'll post more versions when some progress is made.


Dwachs

Implemented the attraction list slightly different:
local list = world.get_attraction_list()
// list is now of type attraction_list_x
foreach(att in list) {
     ... // att is an instance of the building_x class
}


Quote from: isidoro on January 13, 2014, 04:02:30 PM
To know if two building tiles belong to the same attraction, in this case, I could do the same I do with factories:  ask for the get_pos() method of factory_x and compare the values.
No, get_pos will return the position of the individual tile, thus it will differ for different tiles of the same multi-tile building. I added building_x::is_same_building for this purpose.

Moreover

a.get_pos() == b.get_pos()

wont work, as squirrel does not check the members of instances/arrays/tables. It only checks whether the references (or pointers) to these objects are the same.
Parsley, sage, rosemary, and maggikraut.

isidoro

Thanks again, Dwachs for the inclusion of get_attraction_list.

Attached is the current state of the scenario.  I solved the multi-tile building issue by checking the relevant object (factory, attraction, etc.) instead.  In order to check for equality, I was aware of the issue you mention about coord and check the components instead, as you can see in the code.

Now the first issue I have is that I can check building of factories with tool_build_factory, building of houses with tool_build_house, but I don't have the equivalent: tool_build_attraction

In the scenario attached, there is a lot of debug information, but the main items of the first parts (building materials) is more or less done.

If anyone wants to check it, a nightly nightly of ST and pak128.Britain are needed.  But no serious game can be played now.

Please comment.

Dwachs

There is no separate tool to build attractions, it is included in tool_build_house.

If you set

map.file = "<attach>"

then the scenario can be started in an already existing game.

You record calls to tool_remover. However, the removing may fail even if the scenario allows it. In this case you need to check that the building is indeed deleted.
Parsley, sage, rosemary, and maggikraut.

isidoro

Thanks.  I have corrected that and now the tool_build_house also triggers "possible construction of attractions".

Regarding your remark about the tool_remover, there is no problem with the false positives, since that only triggers the update of the data cached to speed up presentation.  Some extra calculations are done, but nothing that really alters the final outcome.

Now, I'll go for the food+clothes issue.  When I have that part done, I'll post the scenario file again.

isidoro

Self-reply.  ;)
I feel like John the Baptist preaching in the desert...  This time food is nearly done.  Next, clothes.

One question: is it possible to know in what fraction of the month the game is?

Dwachs

Parsley, sage, rosemary, and maggikraut.

isidoro

Thanks, Dwachs.  I plan to use it to give a better estimate of present state in the progress window.

In this version, clothes are more or less included.  Some interface polish too.  You can see now your cities grow or shrink depending on whether you adequately supply them or not.

isidoro

I would like to make the demand of clothes depend on climate, so that in colder places more clothes are needed.

But I don't understand very well the climate system.  In the map I am using (double heights), the settings were that winter snowline was height 7 and summer snowline was height 10.  When I run the game, those figures are not followed and have a summer snowline at -11...


kierongreen

That shouldn't happen...

prissi

What is the groundwater level? If this is at 4 then 11 is equal to 7 ...

isidoro

That's certainly the reason.  Thanks, prissi.

Here's a new version.  In this one, natural resources and factory production depends on location on the map and date.  Unfortunately, with today's Squirrel interface I haven't been able to enforce that and the player is asked to follow that rule.

A function that made possible to change the maximum production of an industry from Squirrel would alleviate that somewhat.

Please comment.


isidoro

In this version, a bug is mended.  A custom map, based on the Swiss scenario, is also included.  In order to try it, please use a nightly both of simutrans and pak128.Britain.  Make a directory named scenario in the directory of the pak and unzip the growth directory inside it.

http://simutrans-germany.com/files/upload/growth.zip

I've been playing with it for some time and, although quite difficult to manage, I like the dynamics...

Comments, bugs, etc. are welcome.


isidoro

I'm glad you like it!  Here is my attempt to start with it.  I started to develop three zones where iron and coal were readily available:

       
  • Seaham region: that was my first attempt and made some mistakes.  For example, except for Helmsley, every other village has no building yard => no more buildings.  Seaham is now well provided and you can see the population grow.  Helmsley is too, but has no drinks.  Although it consumes milk!  Milk will be part drink in the next version of the scenario.  Note that Downham had to dig some tiles in order to find clay.
  • Alsager region: my second attempt.  Although not so well developped yet, no mistakes with building materials.  All villages either have a building yard or have credit for a new industry.
  • Lynmouth region: an attempt to make advantage of river Lyn, most of it navigable.  Developping.
http://simutrans-germany.com/files/upload/utopia07.sve


I would like to try and polish the scenario before considering how to improve it.  One thing would be a minimum separation between cities and a range for vehicles, so that they cannot travel forever but has to stop at intermediate halts.

Dwachs

Parsley, sage, rosemary, and maggikraut.