Page 1 of 1

Calculating production

Posted: 02 Mar 2010 15:55
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

Re: Calculating production

Posted: 02 Mar 2010 16:11
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.

Re: Calculating production

Posted: 02 Mar 2010 20:40
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.

Re: Calculating production

Posted: 03 Mar 2010 07:20
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

Re: Calculating production

Posted: 03 Mar 2010 10:02
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.