SuperLib: Helper, Direction, Tile, ... libraries

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

krinn
Transport Coordinator
Transport Coordinator
Posts: 339
Joined: 29 Dec 2010 19:36

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by krinn »

:)
the next question is then : what 90 % 100 will gave you
Kogut
Tycoon
Tycoon
Posts: 2493
Joined: 26 Aug 2009 06:33
Location: Poland

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by Kogut »

krinn wrote::)
the next question is then : what 90 % 100 will gave you
% is a modulo operation ( http://en.wikipedia.org/wiki/Modulo_operation )
Correct me If I am wrong - PM me if my English is bad
AIAI - AI for OpenTTD
krinn
Transport Coordinator
Transport Coordinator
Posts: 339
Joined: 29 Dec 2010 19:36

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by krinn »

Well, seems you need more explain so :

Code: Select all

(money % 100) * _SuperLib_Money.GetInflationRate();
Say GetInflationRate = 300
Say we will use your exemple of 90 for money
So it should gave (0.9) * 300 = 270
In real it gives (0) * 300 = 0

And you propose this fix : 0 + 90 * 300 = 27000

Well, if the function is buggy and return 0 instead of 270, i don't think your fix is any better by returning 27000
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by Zuu »

krinn wrote:Well, seems you need more explain so :

Code: Select all

(money % 100) * _SuperLib_Money.GetInflationRate();
Say GetInflationRate = 300
Say we will use your exemple of 90 for money
So it should gave (0.9) * 300 = 270
In real it gives (0) * 300 = 0

And you propose this fix : 0 + 90 * 300 = 27000

Well, if the function is buggy and return 0 instead of 270, i don't think your fix is any better by returning 27000
90 % 100 => 90
110 % 100 => 10

Basically, if you do a division on paper and pen and do it the lazy way, you will first calculate how many whole parts you can break up the numerator in. Second you have a rest number to divide to get the decimal point result. What the modulo operator does here is that it returns the rest number.

There is also details on how it work on negative numbers etc. that I leave out now and suggest that your read up on wikipedia or a text book. The modulo operator is far too useful in programming to not knowing it.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Steffl
Engineer
Engineer
Posts: 103
Joined: 23 Feb 2010 15:44

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by Steffl »

Kogut wrote:

Code: Select all

	return (money / 100) * _SuperLib_Money.GetInflationRate();
I am not sure whatever it is OK that money%100 is ignored (for example Inflate(90) will always return 0).

Maybe

Code: Select all

	return (money / 100) * _SuperLib_Money.GetInflationRate() + (money % 100) * _SuperLib_Money.GetInflationRate();
?

On the other hand - it is hard to imagine that such amount of money will be used in AI code.


I'm not sure if I understand you. Are you trying to say this function returns 0 when you call it with money < 100?
Maybe try this:

Code: Select all

return (((money).tofloat() / 100) * _SuperLib_Money.GetInflationRate()).tointeger()
But isn't the result in a divison not always a float? I'm unsure.

Code: Select all

	return (money / 100) * _SuperLib_Money.GetInflationRate() + (money % 100) * _SuperLib_Money.GetInflationRate();
This should work, too. But you forgot to divide through 100 in your calculation with modulo because _SuperLib_Money.GetInflationRate() is a percent value.

Code: Select all

	return (money / 100) * _SuperLib_Money.GetInflationRate() + ((money % 100) * _SuperLib_Money.GetInflationRate())/100;


Edit: I read this thread again, and I can't think why the solution by Zuu would not work. In my AI I always used .tointeger() after a division to convert it back to integer, so of course it's a float then...
I think now Kogut just got confused by the division through 100. You maybe would do it intentially at the end of calculation, but its done first, to keep a low number for avoiding overflow.
krinn
Transport Coordinator
Transport Coordinator
Posts: 339
Joined: 29 Dec 2010 19:36

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by krinn »

integer && integer gave an integer result, that's why the 0 result.

the real solve is easy you must force a float

Code: Select all

return (money * 0.01 * _SuperLib_Money.GetInflationRate()).tointeger();
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by Zuu »

Original:

Code: Select all

	return money * _SuperLib_Money.GetInflationRate() / 100;
Solution by Kogut, but with added "/100" at the end:

Code: Select all

	return (money / 100) * _SuperLib_Money.GetInflationRate() + (money % 100) * _SuperLib_Money.GetInflationRate() / 100;

Personally I like this integer only solution better than using floats. The result of a floating point operation is always risky unless you have complete knowledge how different platforms etc. influence the result. I can't say that I know how the Squirrel floats change in behaviour on different platforms. I would guess that it uses native division rather than implementing its own division operation. Thus it depends on the native platform exactly what result you get.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by Zuu »

Update - Version 36

Changes:

Code: Select all

Fix:
- Money.Inflate was discarding amounts below 100 money units.

Feature:
- Helper.HasWorldGenBug() - Method to check if OpenTTD is affected by FS#5561 (DoCommands returning 
id 0 for all objects created in world gen)
For more info on FS#5561: http://bugs.openttd.org/task/5561
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Kogut
Tycoon
Tycoon
Posts: 2493
Joined: 26 Aug 2009 06:33
Location: Poland

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by Kogut »

After refactoring of AIAI I have some candidates for SuperLib functions

Helper

Code: Select all

	//from AIAI by Kogut
	//estimates how weight of vehicle will change after loading one piece of cargo_id cargo
	//it is a guess, but there is no better method for predicting this value
	//returns expected weight of single piece of cargo_id
	//GetWeightOfOneCargoPiece(cargo_id)

	//from AIAI by Kogut
	//iterates over vehicles, all stopped in depots are sold
	//SellAllVehiclesStoppedInDepots()

	//from Rondje om de kerk
	//computes square root of i using Babylonian method
	//returns n that is the highest integer that is lower or equal to the square root of integer i
	//Sqrt(i)

	//from Rondje om the kerk
	//attempt to construct HQ in the biggest city, returns true if HQ exists on exiting function, false otherwise
	//if HQ exists on calling function it will not be moved and function will return true
	//BuildCompanyHQ()
Rail

Code: Select all

	//from AIAI by Kogut
	//attempts to locate brake van - wagon appearing in some newgrfs (for example - Japanese Train Set v2.1a), required to start freight train
	//search is limited to ones usable on specified railtype
	//returns engine_id of the fastest one or null if none was found
	//GetBrakeVan(railtype)

	//from AdmiralAI by Thijs Marinussen
	//constructs RailDepot and connects it to railway supplied in path parameter, may perform some landscaping to allow construction of the depot
	//Returns a depot tile if successful, null otherwise 
	//BuildDepot(path);
Town

Code: Select all

	//from AIAI by Kogut, based on function from AdmiralAI by Yexo 
	//Plant trees around town town_id to improve rating till it is at least min_rating, stop if amount of available money drops below money_threshold
	//return true on success (rating is at least as high as min_rating), false otherwise
	//PlantTreesToImproveRating(town_id, min_rating, money_threshold)
Is there a place for some of them in this library? I would provide modified SuperLib with wanted function(s) added in the correct coding style.
Correct me If I am wrong - PM me if my English is bad
AIAI - AI for OpenTTD
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by Zuu »

I don't see any reason to not accept any of those methods based on the description of them.

Out of the Helper methods, I would prefere to place SellAllVehiclesStoppedInDepots() in the Vehicle sub library.

Ideally I think GetWeightOfOneCargoPiece(cargo_id) should go into a new Cargo sub library. However, I know that there is eg. GetPAXCargo() in Helper already, so because of that I agree to place GetWeightOfOneCargoPiece(cargo_id) in Helper.


As for the contribution, I would suggest that you clone the HG repository, make the changes and run hg diff to create a patch file rather than sending me a complete copy of SuperLib.

Code: Select all

hg clone http://hg.openttdcoop.org/superlib superlib
cd superlib

# make changes
vim vehicle.nut
vim rail.nut
#...
vim changelog.txt

hg diff > changes.patch

# Upload changes.patch

If you want to do it even prettier you can create one patch for each added method: (in this case, each added method is fairly independent of each other, so the point of splitting it up is not very high, but this is how to create a patch queue with hg)

Code: Select all

hg clone http://hg.openttdcoop.org/superlib superlib
cd superlib

# init hg queues
hg qinit

# make change 1
hg qnew "10-vehicle-depot-sell.patch"
vim superlib/vehicle.nut
vim changelog.txt
hg qrefresh -m "Add: Vehicle.SellAllVehiclesStoppedInDepots()"

# make change 2
hg qnew "20-rail-methods.patch"
vim superlib/rail.nut
vim changelog.txt
hg qrefresh -m "Add: Additional rail helpers"

# Upload the patches in .hg/patches/
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
HGus
Engineer
Engineer
Posts: 121
Joined: 12 May 2013 22:28
Location: Argentina

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by HGus »

Kogut wrote:After refactoring of AIAI I have some candidates for SuperLib functions

Helper

Code: Select all

...
	//from Rondje om de kerk
	//computes square root of i using Babylonian method
	//returns n that is the highest integer that is lower or equal to the square root of integer i
	//Sqrt(i)
...
sqrt() is already included in Squirrel math api
krinn
Transport Coordinator
Transport Coordinator
Posts: 339
Joined: 29 Dec 2010 19:36

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by krinn »

HGUS wrote:sqrt() is already included in Squirrel math api
But the math api isn't include in openttd...
(And even if, did you check the squirrel sqrt use the the babylonian method too ?)
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by Zuu »

Quote from post in MinimalGS thread that is related to a SuperLib method which is not used in MinimalGS (v2). I therefore answer it here.
krinn wrote:I get a look at it, i suggest (not critical) it would be better if function NewStoryPage(company, title, ...) return an array of [page_id, pe, pe, pe...]
With page_id user may use the id to re-add other elements in the page, but your function is there to add multi-elements in a row, so re-use of page_id is not really as useful as editing existing element id.

And as it's then a need to return an array for all "pe"_ids it's then logic to add page_id as 0 index while you're at it, and user get all ids he may need to edit elements or add new element to a page.

As i said, really not critical, as it's an example and it already do its task, as the usage is clear even right now.
If you look further down in story.nut, you will see that there is a Story.NewStoryPage2 which does what you want. I did not want to break scripts relaying on the old return value which may blindly update to next SuperLib due to Bananas constraints. So therefore there is a second version with a different return value.

Also, yes there are situations when you may want to add content later, but use it with care as the possibility for users to discover that is more limited than when new pages are added.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
krinn
Transport Coordinator
Transport Coordinator
Posts: 339
Joined: 29 Dec 2010 19:36

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by krinn »

Quiet funny you already did it in fact :)

But really my comment was about the implementation that is within the minimalGS (main.nut line 37) where the same function appears.
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by Zuu »

krinn wrote:Quiet funny you already did it in fact :)

But really my comment was about the implementation that is within the minimalGS (main.nut line 37) where the same function appears.
Neither MinimalGS version 1 nor version 2 has that method. You probably refer to http://devs.openttd.org/~zuu/goal-gui/G ... -GS-v2.tar which is linked to from the Story Book wiki page. But that is not the same as Minimal GS.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
krinn
Transport Coordinator
Transport Coordinator
Posts: 339
Joined: 29 Dec 2010 19:36

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by krinn »

hmmm, well, heu, hmmm...

yes :oops:
R2dical
Traffic Manager
Traffic Manager
Posts: 163
Joined: 18 Mar 2013 22:22

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by R2dical »

Heya,

Bug report for SuperLib v36:

SuperLib.Direction LINE 166 -> "in_direction" should be "dir", and causes a crash as is.

---

Also I have a suggestion function for that same class, similar to the function above (function _SuperLib_Direction::GetDirectionToTile(tile1, tile2)) with the error:

Code: Select all

	/* Returns the direction tile2 is from tile1.
	 * Tiles do not have to be adjacent or exactly on compass axis.
	 * If directly on the axis it will be NE/SE/SW/NW, else it will
	 * be N/E/S/W.
	 */
	static function GetDirectionBetweenTile(tile1, tile2);

Code: Select all

function _SuperLib_Direction::GetDirectionBetweenTile(tile1, tile2)
{
	local rel_x = AIMap.GetTileX(tile2) - AIMap.GetTileX(tile1);
	local rel_y = AIMap.GetTileY(tile2) - AIMap.GetTileY(tile1);

	// Same tile
	if(rel_x == 0 && rel_y == 0) return _SuperLib_Direction.DIR_INVALID;
	// On the same axis.
	else if (rel_x == 0 && rel_y > 0) return _SuperLib_Direction.DIR_NW;
	else if (rel_x == 0 && rel_y < 0) return _SuperLib_Direction.DIR_SE;
	else if (rel_x > 0 && rel_y == 0) return _SuperLib_Direction.DIR_NE;
	else if (rel_x < 0 && rel_y == 0) return _SuperLib_Direction.DIR_SW;
	// Off axis.
	else if (rel_x > 0 && rel_y > 0) return _SuperLib_Direction.DIR_N;
	else if (rel_x < 0 && rel_y < 0) return _SuperLib_Direction.DIR_S;
	else if (rel_x > 0 && rel_y < 0) return _SuperLib_Direction.DIR_E;
	else if (rel_x < 0 && rel_y > 0) return _SuperLib_Direction.DIR_W;
	
	// Error
	return _SuperLib_Direction.DIR_INVALID
}
HGus
Engineer
Engineer
Posts: 121
Joined: 12 May 2013 22:28
Location: Argentina

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by HGus »

Sorry OT:
krinn wrote:
HGUS wrote:sqrt() is already included in Squirrel math api
But the math api isn't include in openttd...
(And even if, did you check the squirrel sqrt use the the babylonian method too ?)
Actually it is, and it is a wrapper to the standard library api, so it is very much faster than any scripted method... :)

And about R2dical suggestion, you don't need to create a new api function, just copy the code in the existing one, cause it is same code rewritten (I'm not sure for better readability or speed, but more compact)
R2dical
Traffic Manager
Traffic Manager
Posts: 163
Joined: 18 Mar 2013 22:22

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by R2dical »

HGus wrote:And about R2dical suggestion, you don't need to create a new api function, just copy the code in the existing one, cause it is same code rewritten (I'm not sure for better readability or speed, but more compact)
The function I suggested is different in that it will always return a direction (except if the tiles are the same). The current superlib function will only return N,E,S,W,NE, etc if it lies EXACTLY on these compass points. i,e for any given radius it will only return a direction for 8 distinct tiles (the 4 diagonals and 4 adjacents), all others return INVALID. The suggested function is useful to analyse tiles that are quite far from each other.
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: SuperLib: Helper, Direction, Tile, ... libraries

Post by Zuu »

Thanks for your contribution. I now see that I've missed a bug report some posts up. Sorry for this delay. No fix yet, but will make one soon.
My OpenTTD contributions (AIs, Game Scripts, patches, OpenTTD Auto Updater, and some sprites)
Junctioneer (a traffic intersection simulator)
Post Reply

Return to “OpenTTD AIs and Game Scripts”

Who is online

Users browsing this forum: peter1138 and 2 guests