Bool/Int confusion: Bug or feature?

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
User avatar
Simons Mith
Transport Coordinator
Transport Coordinator
Posts: 326
Joined: 14 Jan 2010 23:45

Bool/Int confusion: Bug or feature?

Post by Simons Mith »

If you had a code fragment something like this

Code: Select all

	local area = AITileList();
	area.AddRectangle(AITown.GetLocation(town) - 3, AITown.GetLocation(town) + 3);
	area.Valuate(AITile.IsBuildableRectangle, 2, 2);
	area.KeepValue(1); // true=buildable, false=not, but you have to use a numeric value here
the Valuate function returns true for buildable and false for not. But you can't use area.KeepValue(true); because you get complaints of a type mismatch, so you have to use the correct numeric value for true instead. And if you used some other non-zero value (even though all non-zero values are technically also 'true'), then I'd expect the code to fail.

Whenever possible, I always prefer to write code that says precisely what I mean (so in this instance I'd want to use area.KeepValue(true); as that's what I'm actually testing for.) Is the current behaviour an easily-fixed oversight, or is it considered correct (if so, why?), or is it something I'll have to live with? I don't mind which, but I'd like to know the devs' coding philosophy on areas like this. Thanks.
krinn
Transport Coordinator
Transport Coordinator
Posts: 342
Joined: 29 Dec 2010 19:36

Re: Bool/Int confusion: Bug or feature?

Post by krinn »

in nearly all language, 0 & 1 mean also boolean result

i think you are more complaining about "Why the f*** this doesn't work", then "why the hell a boolean is 1 or 0"

And your answer is:
You are failing because (AITown.GetLocation - 3) & AITown.GetLocation + 3 = same line -> you're not taking a rectangle and the 2nd test could then only fail (try to find 2 squares buildable area in a flat area).

area.AddRectangle(AITown.GetLocation + AIMap.GetTileIndex(3, 3), AITown.GetLocation - AIMap.GetTileIndex(3,3))
User avatar
Simons Mith
Transport Coordinator
Transport Coordinator
Posts: 326
Joined: 14 Jan 2010 23:45

Re: Bool/Int confusion: Bug or feature?

Post by Simons Mith »

Oh, bother and blast. That code was taken from a fragment of code that /does/ work, perfectly. But I broke it when I shortened it and posted it here, in just the way you explain, and that's very annoying because it distracts from my actual query. Here's the unaltered version of the entire function that does work with a (1) and doesn't work with a (true). I can post the entire AI too if you like. My original question stands, and sorry for needlessly confusing matters.

Code: Select all

function BuildHQ::FindSuitableArea(town) {
	local area = AITileList();
	local inner_radius = (AITown.GetPopulation(town) / 1000); // 2 square radius for pop. 2000
	// Divider of about 500-1000 seems reasonable.
	local outer_radius = inner_radius + 3;
	AILog.Info("Inner radius " + inner_radius);
	AILog.Info("Outer radius " + outer_radius);
	area.AddRectangle(AITown.GetLocation(town) - AIMap.GetTileIndex(outer_radius,outer_radius), AITown.GetLocation(town) + AIMap.GetTileIndex(outer_radius,outer_radius));
	area.RemoveRectangle(AITown.GetLocation(town) - AIMap.GetTileIndex(inner_radius,inner_radius), AITown.GetLocation(town) + AIMap.GetTileIndex(inner_radius,inner_radius));
	area.Valuate(AITile.IsBuildableRectangle, 2, 2);
	area.KeepValue(true); // Strictly, true = buildable, false = not, but you can't use a boolean here
	area.Valuate(AIMap.DistanceManhattan, AITown.GetLocation(town));
	area.Sort(AIAbstractList.SORT_BY_VALUE, AIAbstractList.SORT_DESCENDING);
	return area;
}
KeepValue(true), as above, fails. Change just that one line in the entire AI to KeepValue(1) and it works as expected.
krinn
Transport Coordinator
Transport Coordinator
Posts: 342
Joined: 29 Dec 2010 19:36

Re: Bool/Int confusion: Bug or feature?

Post by krinn »

Well then it's just because KeepValue works with integer, and even a boolean use 1 and 0 that are part of integer, a boolean isn't an integer.

Many languages provide a "i want typecast that" function
if i'm right squierrel have a tointeger typecast (look in the manual for the real function name)
KeepValue(TRUE._tointeger()); <- i'm not sure you can do that on a reserved word, but this will at least show you a wanted typecast by user.

But you can make your own true or false but still as integer if you really like to use a "word" for that
local myTRUE = 1;
local myFALSE = 0;
area.KeepValue(myTRUE);

this will work, as myTRUE will be integer and KeepValue is expecting an integer to come
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: Bool/Int confusion: Bug or feature?

Post by Yexo »

AIList can only contain int values, no bools. That is by design. Since it's very useful (as you've found) to filter lists by a function that returns a boolean value, Valuate converts a bool return value to 0/1. That is a special case in valuate. KeepValue/RemoveValue know nothing about that and just deal with the actual value in the list, which is an int (0/1 for bools).

It could've designed in another way by creating another function like AIList.Filter(function_returning_bool) that doesn't change any of the values but just removes those items where the function returned false.
Post Reply

Return to “OpenTTD AIs and Game Scripts”

Who is online

Users browsing this forum: No registered users and 8 guests