Pastebin launched a little side project called HostCabi.net, check it out ;-)Don't like ads? PRO users don't see any ads ;-)
Guest

Matchbox maze - initial solution

By: Apjjm on Apr 24th, 2012  |  syntax: C  |  size: 6.79 KB  |  hits: 27  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. const string MATCHBOX = "matchbox";
  2. const string WALL = "shelfwall_";
  3. const string RAY_SEGMENT_FILE = "sdiv";
  4.  
  5. void OnStart()
  6. {
  7.   //#1: Create the detectors & init vats
  8.   CreateDetectors(MATCHBOX,RAY_SEGMENT_FILE,0.5f,10);
  9.   //#2: Set the initial direction
  10.   SetCurrentDir(EAST);
  11.   //#3: Wait until the crate hits the floor (2 seconds)
  12.   AddTimer("TMR_CRATE_MOVE",2.0f,"tmrCrateMotion");
  13. }
  14.  
  15. ///////////////////////////////
  16. //+ DETECTOR INIT
  17. ///////////////////////////////
  18. //Create a set of wall detectors around the matchbox
  19. void CreateDetectors(string &in asEntity, string &in asFileBase, float afStepSize, int maxDetectors)
  20.  {
  21.    string filename = asFileBase + afStepSize + ".ent";
  22.    
  23.    //Create the beam of detectors
  24.    for(int i = 0; i < maxDetectors; i++)
  25.     {
  26.           float pos = afStepSize * i;
  27.           //East detectors (X+)
  28.           CreateWallDetector(pos,filename,asEntity,EAST, i);
  29.           //West detectors (X-)
  30.           CreateWallDetector(pos,filename,asEntity,WEST, i);
  31.           //North detectors (Z+)
  32.           CreateWallDetector(pos,filename,asEntity,NORTH, i);
  33.           //South detectors (Z-)
  34.           CreateWallDetector(pos,filename,asEntity,SOUTH, i);
  35.         }
  36.        
  37.    //Calculate the min detectors
  38.    @RayCastCondition = @rccMatchboxInit;
  39.    SetMinDir(NORTH); SetMinDir(SOUTH); SetMinDir(EAST); SetMinDir(WEST);
  40.    @RayCastCondition = @rccWall;
  41.  }
  42.  
  43. //Create a single wall detector
  44. void CreateWallDetector(float afAmt, string &in asFileName, string &in asAttachBase, Direction dir, int alIndex)
  45.  {
  46.    string dname = DirectionPrefix(dir) + alIndex;
  47.    AttachProp(asAttachBase,dname,asFileName, Xcomp(dir) * afAmt, Ycomp(dir) * afAmt, Zcomp(dir) * afAmt);
  48.  }
  49.  
  50. //Fixed variant of AddAttachedPropToProp
  51. void AttachProp(string &in asPName,string &in asAName, string &in aFile, float afX, float afY, float afZ) { AddAttachedPropToProp(asPName,asAName,aFile,afX,afY,0,afZ,90.0f,afZ); }
  52. ///////////////////////////////
  53. //- DETECTOR INIT
  54. ///////////////////////////////
  55.  
  56. ///////////////////////////////
  57. //+ CRATE MOTION
  58. ///////////////////////////////
  59. float TIMESTEP = 1.0f / 5.0f;
  60. void tmrCrateMotion(string &in asTimer)
  61.  {
  62.     Direction dir = GetCurrentDir();
  63.         //Move the crate forward
  64.         float impulse = 1.0f;
  65.         AddPropImpulse(MATCHBOX, impulse * Xcomp(dir), impulse * Ycomp(dir), impulse * Zcomp(dir), "world");
  66.         //Raycast forward -> Are we at the wall?
  67.         @RayCastCondition = @rccWall;
  68.         AddDebugMessage("RCV: " + RayCast(dir),false);
  69.         if(RayCast(dir) <= GetMinDir(dir))
  70.          {
  71.            AddDebugMessage("At end of path. Picking new direction.",false);
  72.            SetCurrentDir(SelectBestDirection(dir));
  73.          }
  74.         AddTimer(asTimer,TIMESTEP,"tmrCrateMotion");
  75.  }
  76.  
  77. //Select the best direction by seeing which way has the longest distance box can move (excluding where box came from)
  78. Direction SelectBestDirection(Direction oldDirection)
  79.  {
  80.     //Get a collection of directions the box can move in
  81.         Direction[] newDirections = GetNewDirections(oldDirection);
  82.        
  83.         //Assume first defined direction is best for now
  84.         Direction bestDirection = newDirections[0];
  85.         int bestValue = RayCast(newDirections[0]);
  86.        
  87.         //Look through all remaining possible directions to pick best path
  88.         for(uint i = 1; i<newDirections.length(); i++)
  89.          {
  90.            int newValue = RayCast(newDirections[i]);
  91.            if(newValue > bestValue)
  92.             {
  93.                   //Longer path than before - this is now the best direction to move
  94.                   bestValue = newValue;
  95.                   bestDirection = newDirections[i];
  96.                 }
  97.          }
  98.        
  99.         AddDebugMessage(DirectionPrefix(oldDirection) + " -> " + DirectionPrefix(bestDirection) + " (" + bestValue + ")",false);
  100.         return bestDirection;
  101.  }
  102.  
  103. //Get all the directions the box can move excluding where the box came from
  104. Direction[] GetNewDirections(Direction oldDirection)
  105.  {
  106.         switch(oldDirection)
  107.          {
  108.            case NORTH: return DS03;
  109.            case SOUTH: return DS04;
  110.            case EAST:  return DS01;
  111.            case WEST:  return DS02;
  112.          }
  113.         return DS00;
  114.  }
  115.  
  116. Direction[] DS00 = {NORTH, SOUTH, EAST, WEST};
  117. Direction[] DS01 = {NORTH, SOUTH, EAST};
  118. Direction[] DS02 = {NORTH, SOUTH, WEST};
  119. Direction[] DS03 = {NORTH, EAST, WEST};
  120. Direction[] DS04 = {SOUTH, EAST, WEST};
  121.  
  122. ///////////////////////////////
  123. //- CRATE MOTION
  124. ///////////////////////////////
  125.  
  126. ///////////////////////////////
  127. //+ RAY CASTING
  128. ///////////////////////////////
  129.  
  130. //Returns how many ray segments in the given direction there are until a collision occurrs
  131. int RayCast(Direction dir)
  132.  {
  133.   string pfx = DirectionPrefix(dir);
  134.   int i =0;
  135.  
  136.   for(; GetEntityExists(pfx+i); i++)
  137.         if(RayCastCondition(pfx+i)) return i;
  138.  
  139.   return i;
  140.  }
  141.  
  142. //used to determine if the raytrace should continue
  143. funcdef bool RAYCASTCONDITION(string &in);
  144. RAYCASTCONDITION @RayCastCondition = @rccWall;
  145.  
  146. //returns true if ray segment collides with a wall (used for detector)
  147. bool rccWall(string &in asRaySegment)
  148.  {
  149.    //i<100 to get around missing wall peices.
  150.    for(int i = 1; i < 100; i++)
  151.           if(GetEntitiesCollide(WALL+i,asRaySegment)) return true;
  152.    return false;
  153.  }
  154.  
  155. //returns true if ray segment doesn't collide with the matchbox (used in init)
  156. bool rccMatchboxInit(string &in asRaySegment)
  157.  { return !GetEntitiesCollide(MATCHBOX,asRaySegment); }
  158.  
  159. ///////////////////////////////
  160. //- RayCasting
  161. ///////////////////////////////
  162.  
  163. ///////////////////////////////
  164. //+ DIRECTION ENUM
  165. ///////////////////////////////
  166. enum Direction
  167.  {
  168.    NORTH,
  169.    SOUTH,
  170.    EAST,
  171.    WEST
  172.  }
  173.  
  174. //Prefix of a given direction
  175. string DirectionPrefix(Direction dir)
  176.  {
  177.    switch(dir)
  178.     {
  179.           case NORTH: return "N";
  180.           case SOUTH: return "S";
  181.           case EAST: return "E";
  182.           case WEST: return "W";
  183.         }
  184.         AddDebugMessage("Error: Unknown direction error",false);
  185.         return "?";
  186.  }
  187.  
  188. //Get/Set the min value for a direction
  189. void SetMinDir(Direction dir)
  190.  {
  191.   string vn = "MIN_" + DirectionPrefix(dir);
  192.   SetLocalVarInt(vn,RayCast(dir));
  193.   AddDebugMessage(vn + ":" + GetLocalVarInt(vn),false);
  194.  }
  195.  
  196. int GetMinDir(Direction dir)
  197.  {
  198.         return GetLocalVarInt("MIN_" + DirectionPrefix(dir));
  199.  }
  200.  
  201. //Get/Set current direction
  202. void SetCurrentDir(Direction dir)
  203.  {
  204.         switch(dir)
  205.     {
  206.           case NORTH: SetLocalVarInt("CDIR",1); break;
  207.           case SOUTH: SetLocalVarInt("CDIR",2); break;
  208.           case EAST: SetLocalVarInt("CDIR",3); break;
  209.           case WEST: SetLocalVarInt("CDIR",4); break;
  210.         }
  211.  }
  212.  
  213. Direction GetCurrentDir()
  214.  {
  215.         switch(GetLocalVarInt("CDIR"))
  216.     {
  217.           case 1: return NORTH;
  218.           case 2: return SOUTH;
  219.           case 3: return EAST;
  220.           case 4: return WEST;
  221.         }
  222.         return NORTH;
  223.  }
  224.  
  225. //Components of direction
  226. float Xcomp(Direction dir) { switch(dir) { case EAST: return 1.0f; case WEST: return -1.0f; } return 0.0f; }
  227. float Ycomp(Direction dir) { return 0.0f; }
  228. float Zcomp(Direction dir) { switch(dir) { case NORTH: return 1.0f; case SOUTH: return -1.0f; } return 0.0f; }
  229.  
  230. ///////////////////////////////
  231. //- DIRECTION ENUM
  232. ///////////////////////////////