foreach in switch statement breaks?

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
Morloth
Transport Coordinator
Transport Coordinator
Posts: 378
Joined: 07 Feb 2008 14:06
Location: Glasgow

foreach in switch statement breaks?

Post by Morloth »

Hey everyone,

I was working to get rid of any HasNext instance in the code and I came across a weird problem. Please consider the following code:

Code: Select all

function PathBuilder::BuildRoadPiece(fromTile, toTile, tileType, length, estimateCost) {

	local buildSucceded = false;
	
	switch (tileType) {
		
		case Tile.ROAD:
			...
			break;
			
		case Tile.TUNNEL:
			...
			break;
			
		case Tile.BRIDGE:
			// Find the cheapest and fastest bridge.
			local bridgeTypes = AIBridgeList_Length(length);
			local bestBridgeType = null;
//			for (local bridge = bridgeTypes.Begin(); bridgeTypes.HasNext(); bridge = bridgeTypes.Next()) {
			foreach (bridge, value in bridgeTypes) {
				if (bestBridgeType == null || (AIBridge.GetPrice(bestBridgeType, length) > AIBridge.GetPrice(bridge, length) && AIBridge.GetMaxSpeed(bridge) >= maxSpeed))
					bestBridgeType = bridge;
			}
		
			// Connect the bridge to the other end. Because the first road tile after the bridge has to
			// be straight, we have to substract a tile in the opposite direction from where the bridge is
			// going. Because we calculated the pathlist in the other direction, the direction is in the
			// opposite direction so we need to add it.
			buildSucceded = AIBridge.BuildBridge(AIVehicle.VT_ROAD, bestBridgeType, fromTile, toTile);
			break;
			
		default:
			assert(false);
	}
	
	// Next check if the build was succesful, and if not store all relevant information.
	if (!buildSucceded) {
		
		// If the error is such we are unable to solve, stop.
		if (!estimateCost && !CheckError([fromTile, toTile, tileType, length]))
			return false;
	}
	
	return true;
}
When I replace the line

Code: Select all

for (local bridge = bridgeTypes.Begin(); bridgeTypes.HasNext(); bridge = bridgeTypes.Next()) {
with

Code: Select all

foreach (bridge, value in bridgeTypes) {
I get the error: Your script made an error the index 'buildSucceded' does not exist on the line:

Code: Select all

	// Next check if the build was succesful, and if not store all relevant information.
	if (!buildSucceded) {
When I change is back everything works normally, does anyone has an idea what is going on here?

Thanks in advance!
Bram
Morloth
Transport Coordinator
Transport Coordinator
Posts: 378
Joined: 07 Feb 2008 14:06
Location: Glasgow

Re: foreach in switch statement breaks?

Post by Morloth »

It seems it's a bug in Squirrel, the following code does work:

Code: Select all

function PathBuilder::BuildRoadPiece(fromTile, toTile, tileType, length, estimateCost) {

   local buildSucceded = false;
   local DUMMY_VARIABLE = 0;
   
   switch (tileType) {
      ...
   }
}
Dwachs
Engineer
Engineer
Posts: 46
Joined: 02 Jun 2005 07:28

Re: foreach in switch statement breaks?

Post by Dwachs »

Just guessing: maybe there is a semi-colon missing as in foreach(bla; bla) ?
User avatar
Zuu
OpenTTD Developer
OpenTTD Developer
Posts: 4553
Joined: 09 Jun 2003 18:21
Location: /home/sweden

Re: foreach in switch statement breaks?

Post by Zuu »

Does it work if you add an explicit block around your case-code? This is sometimes needed in C++ to get scoping right in switch-case statements.

Code: Select all

foreach(..)
{
  case A:
  {
     local x = 5;
     foreach(key, val in list)
     {
        // ..
     }
  }
}
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: foreach in switch statement breaks?

Post by Steffl »

This remembers me to a problem which I had with a foreach loop. I had to set the #opcodes setting higher, then my code worked again. I think it is always a good idea to try this, especially when the code fails on an unexpected place.

edit: I read your post carefully now and think that's not the solution to this here. Maybe you should try to use the 'local' keyword in another line.
Post Reply

Return to “OpenTTD AIs and Game Scripts”

Who is online

Users browsing this forum: No registered users and 7 guests