Calculating production

Discuss the new AI features ("NoAI") introduced into OpenTTD 0.7, allowing you to implement custom AIs, and the new Game Scripts available in OpenTTD 1.2 and higher.

Moderator: OpenTTD Developers

Post Reply
SummerBulb
Engineer
Engineer
Posts: 24
Joined: 06 Feb 2010 22:12

Calculating production

Post by SummerBulb »

Hi.

I've tried to write a small function that calculates the number of busses needed for a bus route. For simplicity reasons, my calculations assume that the AI bus station is the only one in both the source and the destination towns.
The math is based on the following (take from our wiki):
During each cycle of 2.5 days for each cargo type of the delivering industry a maximum of 2 stations can get cargo assigned. If there are more than 2 possible stations with the same maximum rating value for the current cargo type then it depends on internal ordering of the stations which ones get the cargo.

If there's only one possible station then the delivered amount is: produced_amount * station_rating_in_percent, rounded up to the next integer value.
And base on this (also taken from our wiki):
The game has many rules to make vehicles move fairly realistically. A vehicle travelling at 100 mph (160kph) will cross 5.6 tiles per day.

This means that for vehicle speed purposes, a tile is 429 miles (686km) on a side!
For some reason, the amount of busses calculated by the function is way too high.

The function:

Code: Select all

//from,to - town IDs.
function RonitAI::GetBusCount(from, to, busID)
{
	local fromProduction = AITown.GetMaxProduction(from, passenger_cargo_id);
	local toProduction = AITown.GetMaxProduction(to, passenger_cargo_id);
	
	AILog.Info("From production: " + fromProduction);
	AILog.Info("To Production: " + toProduction);
	
	local fromPerDay = fromProduction * 0.6 / 2.5;
	local toPerDay = toProduction * 0.6 / 2.5;
	
	AILog.Info("fromPerDay: " + fromPerDay);
	AILog.Info("ToPerDay: " + toPerDay);
	
	local maxPerDay = fromPerDay;
	if (toPerDay > maxPerDay)
		maxPerDay = toPerDay;
	
	AILog.Info("MaxPerDay: " + maxPerDay);
	
	local engine = AIVehicle.GetEngineType(busID);
	local capacity = AIEngine.GetCapacity(engine);
	local speed = AIEngine.GetMaxSpeed(engine);
	
	AILog.Info("BusCapacity: " + capacity);
	AILog.Info("BusSpeed: " + speed);
	
	local distance = AITile.GetDistanceManhattanToTile(AITown.GetLocation(from), AITown.GetLocation(to)) * 686;
	AILog.Info("Manhattan Distance: " + distance/686);
	AILog.Info("Distance in kiometers: " + distance);
	
	local travelDays = (distance / speed )/ 24;
	AILog.Info("TravelDays: " + travelDays);
	
	local actualProduct = 2 * travelDays * maxPerDay;
	AILog.Info("ActualProduct: " + actualProduct);
	
	local busses = actualProduct / capacity;
	
	AILog.Info("busses: " + busses);
	
	if (busses % 1 != 0)
	{
		busses ++;
		AILog.Info("Increment busses.");
	}
	AILog.Info("Busses: " + busses);
	return busses; 	
}
The output is:

Code: Select all

From production: 244
To Production: 165
fromPerDay: 58.56
ToPerDay: 39.6
MaxPerDay: 58.56
BusCapacity: 31
BusSpeed: 56
Manhattan Distance: 36
Distance in kiometers: 24696
TravelDays: 18
ActualProduct: 2108.16	
busses: 68.0052
Increment busses.
Busses: 69.0052
Any ideas?

BTW, does squirrel support Ceil() and Floor() functions (or RoundUp() and RoundDown())?

Thanks,
SummerBulb
Rubidium
OpenTTD Developer
OpenTTD Developer
Posts: 3815
Joined: 09 Feb 2006 19:15

Re: Calculating production

Post by Rubidium »

Isn't the industry production given by the API a per month figure?

Also the 2.5 days figure seems wrong; cargo ages every 2.5 days. The cargo distribution happens (per tile) every 256 ticks (almost 3.5 days), however whether stuff is moved depends on some thresholds. You talking about busses implies you're talkin about passengers, which are even trickier to predict.
svetovoi
Engineer
Engineer
Posts: 87
Joined: 12 Oct 2007 14:07

Re: Calculating production

Post by svetovoi »

The clause

Code: Select all

local fromPerDay = fromProduction * 0.6 / 2.5;
causes error indeed.
0.6 / 2.5 is about 1/4, so with this code you stated that fromPerDay is about 1/4 from AITown.GetMaxProduction(station certainly will not receive 1/4 of max month production per day).
This code should be fine:

Code: Select all

local fromPerDay = fromProduction / 30;
Such figure is not entirely correct, but it works good as the first approach, and since you anyway will need to adjust number of vehicles per station periodicly(and can't do it accurate, while relying on data such AITown.GetMaxProduction or AIIndustry.GetLastMonthProduction) there is no need to be 100% correct - you will either improve or screw initial value very fast.

toPerDay should be fixed too, of course.
And, probably, you will be more interested in minPerDay = min(fromPerDay, toPerDay), rather than maxPerDay for passengers transportation.
SummerBulb
Engineer
Engineer
Posts: 24
Joined: 06 Feb 2010 22:12

Re: Calculating production

Post by SummerBulb »

ac84 wrote:And, probably, you will be more interested in minPerDay = min(fromPerDay, toPerDay), rather than maxPerDay for passengers transportation.
Why?

i can choose between the following two:
1) Use maxPerDay and have enough vehicles to collect (almost) all the cargo from the stations. This aproach's down side is that when driving from the smaller station to the larger one, some of the vehicles won't be full.
2) Use minPerDay and have my vehicles travel full both directions. This aproach's down side is that the larger station won't have all the cargo collected from and thus will have a rating decrease.

So, why choose option (2) as opposed to option (2)?

Thanks for the comments,
SummerBulb
svetovoi
Engineer
Engineer
Posts: 87
Joined: 12 Oct 2007 14:07

Re: Calculating production

Post by svetovoi »

SummerBulb wrote: Why?
Because of you own point 1
This aproach's down side is that when driving from the smaller station to the larger one, some of the vehicles won't be full.
Sometimes "some of the vehicles" can be about half of total number.
Such situation is not really rare - even average map can have thousands of town pairs, and with maxPerDay the AI decisions "which towns to connect" become pretty random(or you'll have to use method not based on pre-calculated income to choose pair of towns to connect, and it's the same random imho).
E.g. consider Town_BIG(population 2500), Town_BIG_TOO(population 2500) and Town_VERY_SMALL(population 400)
With maxPerDay the AI will not notice difference between Town_BIG <-> Town_BIG_TOO trade and Town_BIG <-> Town_VERY_SMALL, while this difference is rather considerable, if not huge(40 - 45% of income, AI'll spend money for a dozen of useless buses).

Edit: maxPerDay can be better with small maps, when there is only let's say 17 towns, but with hundreds of towns AI always have a better option to spend money than those one-way buses.
Post Reply

Return to “OpenTTD AIs and Game Scripts”

Who is online

Users browsing this forum: No registered users and 6 guests