Announcement

Collapse
No announcement yet.

DEBUG: The GetNearestWater function

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • DEBUG: The GetNearestWater function

    Using the GetNearestWater function as advertised in the slic documentation you get wrong type of arguments errors. Take a look on the source and compare it with the GetNeighbor function:

    Code:
    SFN_ERROR Slic_GetNearestWater::Call(SlicArgList *args)
    {
    	m_result.m_int = 0;
    
    	if(args->m_numArgs != 2)
    		return SFN_ERROR_NUM_ARGS;
    
    	MapPoint pos;
    	if(!args->GetPos(0, pos))
    		return SFN_ERROR_TYPE_ARGS;
    
    	sint32 x, y;
    	MapPoint nearest;
    	sint32 minDist = 0x7fffffff;
    
    	for(y = 0; y < g_theWorld->GetYHeight(); y++) {
    		for(x = 0; x < g_theWorld->GetXWidth(); x++) {
    			if(!g_theWorld->IsWater(x,y))
    				continue;
    			MapPoint chk(x,y);
    			sint32 dist = pos.NormalizedDistance(chk);
    			if(dist < minDist) {
    				minDist = dist;
    				nearest.Set(x,y);
    			}
    		}
    	}
    	if(minDist >= 0x7fffffff) {
    		
    		return SFN_ERROR_OK;
    	}
    
    	if(args->m_argType[1] != SA_TYPE_INT_VAR) {
    		return SFN_ERROR_TYPE_ARGS;
    	}
    
    	SlicSymbolData *sym = args->m_argValue[1].m_symbol;
    	if(sym->GetType() == SLIC_SYM_LOCATION) {
    		m_result.m_int = minDist;
    		sym->SetPos(nearest);
    		return SFN_ERROR_OK;
    	}
    	return SFN_ERROR_TYPE_ARGS;
    }
    Code:
    SFN_ERROR Slic_GetNeighbor::Call(SlicArgList *args)
    {
    	m_result.m_int = 0;
    	if(args->m_numArgs != 3)
    		return SFN_ERROR_NUM_ARGS;
    
    	MapPoint posIn;
    	if(!args->GetPos(0, posIn))
    		return SFN_ERROR_TYPE_ARGS;
    
    	sint32 dir;
    	if(!args->GetInt(1, dir))
    		return SFN_ERROR_TYPE_ARGS;
    
    	MapPoint posOut;
    	if(args->m_argType[2] != SA_TYPE_INT_VAR)
    		return SFN_ERROR_TYPE_ARGS;
    
    	SlicSymbolData *sym = args->m_argValue[2].m_symbol;
    	
    	
    
    	m_result.m_int = posIn.GetNeighborPosition((WORLD_DIRECTION)dir, posOut);
    	sym->SetPos(posOut);
    	return SFN_ERROR_OK;
    }
    Take a close look on the last lines of both functions. The GetNeighbor function returns SFN_ERROR_OK like most of the other functions do. But the GetNearestWater functions returns SFN_ERROR_TYPE_ARGS no idea why.

    I would outcomment three of the last lines like:

    Code:
    	SlicSymbolData *sym = args->m_argValue[1].m_symbol;
    //	if(sym->GetType() == SLIC_SYM_LOCATION) {
    		m_result.m_int = minDist;
    		sym->SetPos(nearest);
    		return SFN_ERROR_OK;
    //	}
    //	return SFN_ERROR_TYPE_ARGS;
    }
    Also in the GetNeigbor function you can't find this location check or what it should be. So I think modify it like this the function should work as advertized.

    -Martin
    Civ2 military advisor: "No complaints, Sir!"

  • #2
    I don't think that's right. This is how it looks to me: The if statement checks that the second argument is in fact a location variable. If it is then it sets and returns OK. If the second variable you pass is not a location then it returns SFN_ERROR_TYPE_ARGS as it should - because the second argument is wrong.

    However, the previous if statement also seems to be checking that the second argument is an integer (Although in a different way), which doesn't seem right...

    Comment


    • #3
      Originally posted by J Bytheway
      I don't think that's right. This is how it looks to me: The if statement checks that the second argument is in fact a location variable. If it is then it sets and returns OK. If the second variable you pass is not a location then it returns SFN_ERROR_TYPE_ARGS as it should - because the second argument is wrong.
      Yes this is the intention but obviously it fails if you pass as second variable a location_t then it returns SFN_ERROR_TYPE_ARGS but if you pass something like city[0].location or location[0].location, or something else's location it doesn't return SFN_ERROR_TYPE_ARGS, but it aslo fails to fill the second argument. Actual this is not surprising, as we don't have write access on the fields.

      Originally posted by J Bytheway
      However, the previous if statement also seems to be checking that the second argument is an integer (Although in a different way), which doesn't seem right...
      So that means if I give the GetNeighbor function as third argument a city_t for instance it wouldn't give me any error message while it is executing.

      -Martin
      Civ2 military advisor: "No complaints, Sir!"

      Comment


      • #4
        Look up the code for sym->SetPos(nearest); and see if you can determine what happens when the sym is not something which shuold be set to a location. If nothing disastrous occurs (like it just returns false) then your solution will probably work. Now I look a little closer at GetNeighbour that does seem likely to be the case.

        Good detective work . Now if I can just make the thing compile...

        Comment


        • #5
          I just tested it and the GetNearestWater function works as advertised. It also accepts any other argument except integers. But I think in that case it does noting with the argument.

          -Martin
          Civ2 military advisor: "No complaints, Sir!"

          Comment


          • #6
            . Glancing at the code for SetPos, I agree that it won't do anything to a non-location. It is set up to handle structs too, but I think that the structs are not implemented - I hope we are able to change that, because structs would be most useful .

            Comment


            • #7
              My guess is that the struct stuff in SLIC is how it handles it's 'builtins', e.g. "city[0].location".

              Comment


              • #8
                Not entirely - there are some lines in the parser allowing you to define your own structs, but they are commented out.

                Comment

                Working...
                X