[SOLVED] Routine stops working after a random number of cycles

Started by LostTrainDude, Fri 17/08/2018 09:31:12

Previous topic - Next topic

LostTrainDude

In my space trading game prototype I have also NPCs who run errands in such way:

  • A new random mission is assigned to them, from the system they are currently on, to a random system (different from the one they are on)
  • They are "flagged" as being on mission
  • They travel from ORIGIN to TARGET
  • Upon arrival on TARGET they are "flagged" as being NOT on mission
  • A new random mission is assigned to them
  • Go to point 2

The problem I have is that this "routine" does not seem to happen "endlessly" as it should. It randomly lasts an average 3 to - maybe - 5 cycles, then the NPC will get a new mission, with new coords, and just sit there, although they are flagged as being "on mission".

I have double checked and the coords are always within the bounds and "real", so I'm not sure what I'm getting wrong. Maybe someone here can provide some feedback?

Here comes the code in the order in which it is compiled:
Code: ags
// Movement uses a pretty basic algorithm.
// Manhattan distance to calculate the distance between the NPC and its target

function Person::Move(int toX, int toY)
{
   int x1 = this.X;
   int y1 = this.Y;
   
   int x2 = toX;
   int y2 = toY;
   
   float tx = IntToFloat(x2 - x1);
   float ty = IntToFloat(y2 - y1);
   
   int dist = GetDistance(this.X, this.Y, x2, y2);
   
   if (dist > 0)
   {
      tx = tx/IntToFloat(dist);
      ty = ty/IntToFloat(dist);
      this.X += FloatToInt(Maths.Ceil(tx));
      this.Y += FloatToInt(Maths.Ceil(ty));
   }
}

Code: ags
/// Move People who are flagged as being on mission towards their destination

function MovePerson(int who)
{
   // The ID of the mission an NPC is on (always 0 in this test)
   int mission_id = People[who].MissionID;
   
   // The ID of the target planet
   int target_planet = Missions[mission_id].TargetPlanet;
   
   // The current X/Y coords of the NPC
   int pX = People[who].X;
   int pY = People[who].Y;
   
   // The X/Y coords of the target planet
   int toX = planetarySystem[target_planet].X;
   int toY = planetarySystem[target_planet].Y;

   // If the NPC is on the target planet
   if (pX == toX && pY == toY)
   {
      // Then is not on mission anymore
      People[who].IsOnMission = false;
      
      // Former target planet becomes new starting position
      People[who].Where = Missions[mission_id].TargetPlanet;
   }     
   else
   {
      // Move towards the target planet
      People[who].Move(toX, toY);
   }
}

Code: ags
// This is the main function who controls the routine

function NextTurn(int turns)
{
   for (int t = 0; t < turns; t++)
   {
      // If NPC (always 0 in this test) is flagged as being on mission
      if (People[0].IsOnMission)
      {
         // Then move NPC (always 0 in this test)
         MovePerson(0);
      }
      else
      {
         // Check that this code is actually being executed
         Display("New Mission!");
         int person = 0; // Always 0 in this test
        
         // Select a random type of mission
         int type = Random(MISSION_TYPES-1);
         
         // Select the starting planet to be the same as the one the NPC is sitting on
         int startPlanet = People[person].Where;
         
         // Select a random target planet
         int targetPlanet = Random(TOTAL_SYSTEMS-1);
         
         // Repeat if start and target planets are the same
         if ((targetPlanet == startPlanet))
         {
            do
            {
               targetPlanet = Random(TOTAL_SYSTEMS-1);
            } while ((targetPlanet == startPlanet));
         }
         
         Missions[0].AssignedTo = 0; // The ID of the NPC to which this mission is assigned
         Missions[0].ID = 0; // The ID of the mission
         Missions[0].OriginPlanet = startPlanet;
         Missions[0].TargetPlanet = targetPlanet;
         Missions[0].Type = type;
         
         People[0].MissionID = 0; // The same as Mission[0].ID
         People[0].IsOnMission = true;
      }
      // Draw the pixels on the screen!
      map.DrawPixelPeople();
   }
}


Code: ags
// This is the debug function I'm using to test the whole thing

function on_key_press(eKeyCode keycode) 
{
   if (keycode == eKey1)
   {
      for (int i = 0; i < 1500; i++)
      {
         NextTurn(1);
         Wait(1); // I want to see it moving on the screen!
      }
   }
}


Thanks in advance and I hope I have made everything clear!

EDIT:

The issue is apparently solved by changing Math.Ceil() to Math.Round() in the Person::Move() function.
vga256 suggested me to go deeper with the debug and I just did that. I'm not sure why the calculation caused the problem, but now it seems to be working as intended!
"We do not stop playing because we grow old, we grow old because we stop playing."

eri0o


LostTrainDude

Quote from: eri0o on Fri 17/08/2018 16:10:20
Hey, you forgot to show the function GetDistance.

You're right!
Here it is:

Code: ags
int GetDistance(int x1, int y1, int x2, int y2)
{   
	float x1f = IntToFloat(x1);
	float x2f = IntToFloat(x2);
	float y1f = IntToFloat(y1);
	float y2f = IntToFloat(y2);
	
	float a = Maths.RaiseToPower((x2f - x1f), 2.0);
	float b = Maths.RaiseToPower((y2f - y1f), 2.0);
	
	float d = Maths.Sqrt(a + b);
	int dist = FloatToInt(d);
	
	return dist;
}
"We do not stop playing because we grow old, we grow old because we stop playing."

SMF spam blocked by CleanTalk