News:

Simutrans Sites
Know our official sites. Find tools and resources for Simutrans.

Price factorials for easy balancing

Started by jamespetts, January 16, 2012, 01:35:31 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

jamespetts

One of the most difficult things about pakset design is price balancing: very large numbers of different objects all need to be balanced precisely against all other objects of all types, and adjusted many times over during testing. This is an enormously laborious task, and can make pakset balancing quite daunting.

A simple idea struck me this afternoon that might make it a great deal more straightforward. I was going to implement it in Experimental, but thought that it might be just as worthwhile for Standard. The idea is to have an adjustable price multiplier for each type of priced object to adjust whole sets of things (for example, vehicle maintenance costs against way purchase costs, etc.) all at once without having to adjust each individual price.

To give an example, suppose that pak.example has three vehicles, with the following running costs:

A: 0.01c
B: 0.10c
C: 0.23c

Suppose that it also has three types of goods with the following revenues:

X: 1.00c
Y: 0.50c
Z: 0.70c

If, during testing, it was found that the players were making profit too easily, and that the running costs of vehicles should be doubled, it would be necessary manually to change all of the prices:

A: 0.02c
B: 0.20c
C: 0.23c

That may be easy in a pakset with three vehicles, but in a pakset with three hundred vehicles, it is an enormous undertaking, especially if one has to do it over and over again to test which of a whole range of values is optimum. The problem is not so much multiplied as squared for each new type of object that needs to be balanced against all the others.

What I suggest, therefore, is that each object type has its own "[object type]_pricefactor" setting, possibly in simuconf.tab. These should be expressed as percentages (perhaps permille?). At 100% (or 1,000 permille, etc.), which would be the default setting, the prices in the game would (in Experimental, subject to scaling) be exactly as entered in the .dat files, as at present. Adjusting the figures would adjust all prices of the type proportionately. So, instead of altering all the vehicles in the pakset, the author of pak.example would simply need to specify:

pricefactor_vehicle_maintenance = 200

in simuconf.tab.

Some matters (and, even if for some reason, this idea is not considered desirable in Standard, I am still interested in thoughts as to how it should be implemented in Experimental) as to implementation details need to be considered. Firstly, how many category subdivisions is it wise to make? For example, do we want a general "pricefactor_vehicle_maintenance" as above, or do we want to be able to separate transport types, so that we get:

pricefactor_vehicle_maintenance_road
pricefactor_vehicle_maintenance_rail
pricefactor_vehicle_maintenance_ship

and so forth? Do we want even to go further and break it down by traction type as follows:

pricefactor_vehicle_maintenance_ship_sail
pricefactor_vehicle_maintenance_ship_biological
pricefactor_vehicle_maintenance_ship_steam

and so forth?

Secondly, is this best in simuconf.tab, or is there some merit in having these adjusted prices set by makeobj and written into the files? My present leaning is towards the former, as it should be easier to code, and would not require pakset recompliation to implement changes.

Some possible benefits of this system include the ability to have different people working on, e.g., vehicles and ways, without knowing how the others have calibrated the prices, and still be able to use the objects in the same game and achieve a balance; pakset balancing can be done much more quickly, and with less need for the use of complicated balancing spreadsheets; balancing can be changed much more quickly if the pakset authors want to make general changes to the pakset (starting in an earlier era, etc.) that require substantial balancing changes; real-life prices can be used (adjusted for inflation) for specific types of vehicles, ways, fares, etc., to balance them against each other, and then the pricefactors can be used to adjust the relative balance of categories to achieve a playable balance overall; and probably many more besides.

I should be interested in people's thoughts.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

ӔO

would this not be of somewhat limited use if many vehicles were imbalanced in the pakset?
I can see this being more useful if it could be changed on the fly as the game progresses with newer, faster vehicles and the vehicles were relatively balanced against each other to start with.
My Sketchup open project sources
various projects rolled up: http://dl.dropbox.com/u/17111233/Roll_up.rar

Colour safe chart:

sdog

My approach, i started but neglected, was to use scripts to create the dat files in the pak from tables with data relevant for the relative pricing. When tweaking i would use general factors for subsets of the objects. (eg all buses) for the relative pricing. Since i would change the scripts on the fly, with if checks for freight type, engine type, waytype etc it would be quite flexible by changing the scripts accordingly.

As i tried to derive the cost from physical factors only (without any concern for historical correctness) only similar vehicles would be reasonably priced compared to each other. Larger groups of objects would be tied together by arbitrary parameters free for tweaking. Some functions (eg cost of fuel, labour etc) would be global. The real art would be to reduce the number for free parameters as much as possible.

Thus in effect it is similar to your suggestion i think, with a less direct implementation though. (which might be easier)

I have not done it though, and can't tell if it is actually feasible.

ps.: a side remark, James if you work through the dat files manually still, you waste quite a lot of time. You really ought to learn regular expressions and scripts. Perl is a very easy approach, but others are also quick to learn. The effort is nothing compared to learning to code in simutrans, and the time spent learning is regained quickly when comparing to manual or search&replace work.

jamespetts

Thank you for your feedback. AEO - the system that I propose would not by itself help with balancing objects of one type against other objects of the same type, but it would very much help in balancing objects of one type against objects of another type. That would then separate the task of balancing, for example, the cost of vehicles against the cost of other vehicles, which would still be done manually in the .dat files, from the task of balancing the cost of vehicles generally against the cost of ways, the revenues, the maintenance cost, and so forth, would would be done with the factorials.

Changing the factorials over time would be quite a different feature, which would need careful (and separate) consideration of its own.

As to the scripts, I suspect that that would be a more difficult approach to price balancing than would the factorials approach, since it would require pakset recompilation to test. The system that I proposed could be tested simply by adjusting simuconf.tab parameters, and would require no pakset recompilation. It would also be easier in that it would use existing tools, structures and systems rather than requiring a set of new tools, structures and systems for balancing.

On working with the .dat files manually, I use MSVC++ to manage them all, which does, I believe, have a regular expressions system built in.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

sdog

"I suspect that that would be a more difficult approach to price balancing than would the factorials approach, since it would require pakset recompilation to test."

i don't see a difficulty there, pakset recompilation takes only a minute or so for the whole pakset. Since for balaning only a subset of the objects would have to get repaked again, it is much faster. Restarting simutrans with the new pakset takes also a bit of time though. This should add about 15 to 30 s between re-balance tests, that makes purely tuning by turning a value until the result is desirable difficult, an iterative approach works well enough though.

Of course the approach you suggested is much more direct, what i wrote was not meant as (negative) criticism on it.


prissi

I think a simple factor would not work; at least faster vehicles are ok to cost more. In my experience, whenever I had to rebalance (like now) it was always never that straight forward.

isidoro

From my point of view, a separate application is better.  With the pass of time, you will want more sophistication in your calculations, a graphical interface, etc.

A separate tool would not increase the memory footprint of the main Simutrans application for something that is going to be used only once (when loading the game).

It's better to plan a new balancing application that allows you to group vehicle in types, describe variables such as labor costs and variation with time.  Input would be a pak set and a description file and output the pak set balanced.  In this application more sophisticated relations among variables can even be tried...


The Hood

I am thinking of coding a script to import dat files into Excel for easy editing (and rebalancing with calculations) and a second script to batch them back out as text files. This is not an immediate priority for me though, but it seems like the most straightforward way.

ӔO

Quote from: isidoro on January 16, 2012, 12:05:48 PM
From my point of view, a separate application is better.  With the pass of time, you will want more sophistication in your calculations, a graphical interface, etc.

A separate tool would not increase the memory footprint of the main Simutrans application for something that is going to be used only once (when loading the game).

It's better to plan a new balancing application that allows you to group vehicle in types, describe variables such as labor costs and variation with time.  Input would be a pak set and a description file and output the pak set balanced.  In this application more sophisticated relations among variables can even be tried...


this is one such program that I have been thinking of as well.
Something that can load several pak and png+dat files with a dat editor and a graphical output to check alignments. Something that can calculate revenue for the capacity and speed the convoy will travel.
My Sketchup open project sources
various projects rolled up: http://dl.dropbox.com/u/17111233/Roll_up.rar

Colour safe chart:

prissi

I my experience with balancing, in the end you have to tweak it manually. This is one of the area where computer can have all the number but still fail to see an image. Like for engine infrastructe maintenance is crucial. But how to determine that in the running costs? And so on.

One can start with a script. But at a certain point, manual intervention is needed. Otherwise it is very easy to end up with only one rational choice.

jamespetts

Hmm, interesting discussion. Firstly, as to an external application: one of the main reasons that I suggested what I did was that writing an entirely separate application would take a great deal more work: adding factorials to Simutrans itself would be quite straightforward, and would add only a trivial amount to the memory consumption (two bytes per factorial for the whole programme). The other advantage is, as previously discussed, pakset recompilation is not necessary for testing. That fewer files have changed would not reduce the time needed for pakset recompilation, at least with the way that Pak128.Britain is done, because there is a script that automatically builds all of the pak files and puts them in a folder along with the configuration files: building, in other words, a complete pakset from sources in a single click. It would take as much work to tinker with this process to export parts of files as just to wait for the whole thing to finish in the first place.

Secondly, what I am suggesting is not intended to be a completely automated system for balancing. I agree with Prissi that a great deal of manual balancing and testing is needed. However, the purpose of the factorials system is not to do away with manual balancing, but make it enormously easier by making it possible to change groups of values all at once. There are many different sorts of possible rebalancing operation: some, such as balancing objects of the same type as against each other, will not benefit from factorials and will need manual editing; others, such as rebalancing the cost of way maintenance generally against the cost of vehicle maintenance generally, will, as a great deal of repetitive work in changing all values of a particular type by a particular factor manually is removed.

Because of the need for some manual element in balancing (necessary, as Prissi points out, because a fully automated system would tend to oversimplify economic choices to the detriment of the playability of the game), working towards a system to have an application for creating .dat files with price values generated entirely automatically is probably not worthwhile. A system whereby financial values as a group can be re-scaled against other financial values as a group is worthwhile for the reasons given previously. If there are people who have the time to write an application that would do that effectively by editing .dat files, and there is some discernable advantage of doing so (memory consumption is not one of them; flexibility as suggested by Isidoro might be), then that might be the way to go. SDog's suggestion of a system that might perform checks on alignment of png files and produce figures that somebody balancing a pakset would find useful would also be worthwhile. However, unless somebody has the time to write such an application in the near future, there is much to be said for something that will at least eliminate the arduousness of balancing one type of thing against another in the meantime (which would not interfere with the goal of an automatic .dat file writer that might check alignments, produce balance calculations, etc., especially as such a calculator could easily just read the values in simuconf.tab and therefore obtain the figures used in the game).
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

sdog

QuoteFirstly, as to an external application: one of the main reasons that I suggested what I did was that writing an entirely separate application would take a great deal more work: adding factorials to Simutrans itself would be quite straightforward, and would add only a trivial amount to the memory consumption (two bytes per factorial for the whole programme).
that is not necessarily correct, writing the external application is not a lot of work, you have to compare it to the increased maintenance for the increased complexity of the simutrans code. if a suitable language is used, the implementation of such a set of scripts is not more work than rewriting simutrans code. more than a set of scripts isn't needed anyway. not to speak of compatibility concerns with legacy pak-sets. There's a reason for the design philosophy to use small programs for each task and sending data from one to another.

QuoteThat fewer files have changed would not reduce the time needed for pakset recompilation, at least with the way that Pak128.Britain is done
if objects are paked in plenty of pak files, or at least a couple of groups, make will just re-pak those necessary. It is also preferable to keep the .dat files in their initial state and run the script only directly before packing the pak set, this is also done easily by including it in the Makefile.

Makefiles are up and running for pak.britain, both experimental and standard. You just need, in a unix-like environment (eg linux, cygwin, mac) copy the config.template file to config.default, configure it (that is mostly giving a path to makeobject) and type make. If it doesn't run anymore, i'll have a look into it, Nathanael updated them a little while ago though.

"Secondly, [...]"
i agree with you there, one step is balancing vehicles of one kind to each other (eg all buses), but whole groups have to be balanced against each other too (eg. bus vs. rail). A common parameter should be quite sensible there. I'd be interested though what Prissi thinks of this, he has next to Frank the most experience with balancing.

Quote
Because of the need for some manual element in balancing (necessary, as Prissi points out, because a fully automated system would tend to oversimplify economic choices to the detriment of the playability of the game), working towards a system to have an application for creating .dat files with price values generated entirely automatically is probably not worthwhile.
that's not how it would work. you can read the existing, manually created .dat file, read out the data, check the type of the object (or tabulate them before), do the calculations and write it back to the file. It isn't a big difference if one auto-creates values with it too, only a few lines of code difference. That's where the flexibility isidoro mentioned comes in too, one can on the fly, without regard to other pak-sets or simutrans version change the equation. Add an offset value, multiply a factor or use a complicated function. If you hard-code it you get quite a lot of parameters, if you want it to be useful. I expect two for each group of objects (offset & factor).

The advantage of your approach of course is, that this could be accesible to the player or server admins. They could just increase all road costs by factor two or make bridges prohibitively expensive. Thus if it is done, make it extensive, a big matrix.


I still want to try, if i can balance a pak-set based on physical properties of the vehicles (number of axles for example). That's a private, fun, project i put a bit back. Mostly out of curiousity, as an experiment. (im in a phase of unusualy low procrastination with my phd project, i'm in fear of getting distracted again -- sorry.)

jamespetts

Hmm - I am only writing from my own knowledge of coding Simutrans, of course; it would certainly be much easier for me to modify the code as I suggested, but if it would be easier for someone else to write an external application to apply factorials (and other things), then that is not something on which I can readily comment. What one may ponder, however, is whether there is a volunteer to do this sort of external application coding, and, if so, what the timeframe is.

If an additional application were to be used, I do rather like your idea of leaving the .dat files alone and changing the numbers on the fly. At this juncture, however, one begins to ask whether one should be modifying Makeobj rather than writing a separate application (having it read from a "balance.conf" file or the sort).

You do make a good point about the level of flexibility that would be useful, which was touched upon in my original post; it would certainly be helpful to be able to balance on multiple parameters.

May I ask - how had you envisaged the third party application working?
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

sdog

application is a big word here, easy to do is to put files with configuration data and the scripts used into the repository. the scripts are small, no gui, data is piped in, goes to std out. Through the makefile they are just called appropriately. The changes you do with tweaking is contained in the equations in the scripts and the data file, that's also what's tracked with the version control.

Now those scripting languages are simple to read, if they are written that way. The pak author should be easily capable to change the lines doing the calculations. Without caring about the in/output or other less relevant stuff. the latter would be portable for other pak sets. Since the input and output format stays the same, the structure of the pak's repository comes from the Makefile.

I'm certain this can be done with mose.py or VS script package for pak128 too, they are written in python i think. I'm mentioning make here since it is already in use for pak.britain.

how urgent is it james?
I wanted to do something like that for quite a while for my pak128 conversion. perhaps i can get to it within the next two weeks. (i'm more reluctant to do the research on the vehicles, writing the scripts is the easier part, i also like better.)

There are a couple of aspects i'm not clear how to do in a good way. It's better i've thought about a way to implement it. Especially i have to take a look into the structure of the dat files, how makeobject gets them and think of a good structure for the data files controling the scripts.

If i get something useful to run, we can talk about adopting it to your requirements. As mentioned before, i want to do quite something different from what you want, but the framework should be almost the same.


"[...] modifying Makeobject [...]"
That's also is a good idea, quite a possible alternative to what i suggested.

jamespetts

Hmm - modifying Makeobj is preferable, I think, to using a script in the way that you suggest above, since the scripts will need to be different for each type of pakset compilation, and depend on a pakset specific workflow, whereas Makeobj is universal. Modifying Makeobj would just need it to read a configuration file containing the factorials; but is this really any easier for pakset authors than putting those same factorials in simuconf.tab?
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

sdog

there is one disadvantage for Makeobj, you change it quite considerably, by changing the data stream. Right now it is passed the .dat file, gets the image location from that and returns the pak. You would have it require for it to have a global configuration file as another dependency.

oh, you could of course also pass the global configuration file in the dat file to makeobj. if there's no line it would ignore it. that way it would stay compatible to the current setup.

jamespetts

Hmm - passing a parameter to a configuration file in every .dat file seems like a very cumbersome way of doing it - wouldn't it be easier for Makeobj just to use 100% defaults when there is no balance.conf file?
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

sdog

you still have to give Makeobj the path to your balance.conf file. present work directory isn't feasible, as pak repositories are often structured in subdirectories. you could pass it as an argument.:w

jamespetts

That would be easier; or have a default directory modifiable by a command line parameter?
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

isidoro

Only a side note, have you seen how MetaPost works?  It is a graphics oriented language and instead of writing all the data (which is also possible), some relations among variables are expressed and the computer does the calculations.  For example, see the way of drawing two intersecting lines here: http://tex.loria.fr/prod-graph/zoonekynd/metapost/metapost.html

beginfig(70)
    pair A,B,C,D,M;
    A=(0,0); B=(2cm,3cm);
    C=(1cm,0); D=(-1cm,2cm);
    M = whatever [A,B];
    M = whatever [C,D];
    draw A--B;
    draw C--D;
    draw M withpen pencircle scaled 4bp;
endfig;