Advertisement
Apjjm

Matchbox maze - initial solution

Apr 24th, 2012
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.79 KB | None | 0 0
  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. ///////////////////////////////
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement