p_maputl.c
上传用户:xuyinpeng
上传日期:2021-05-12
资源大小:455k
文件大小:17k
源码类别:

射击游戏

开发平台:

Visual C++

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. // Movement/collision utility functions,
  21. // as used by function in p_map.c. 
  22. // BLOCKMAP Iterator functions,
  23. // and some PIT_* functions to use for iteration.
  24. //
  25. //-----------------------------------------------------------------------------
  26. static const char
  27. rcsid[] = "$Id: p_maputl.c,v 1.5 1997/02/03 22:45:11 b1 Exp $";
  28. #include <stdlib.h>
  29. #include "m_bbox.h"
  30. #include "doomdef.h"
  31. #include "p_local.h"
  32. // State.
  33. #include "r_state.h"
  34. //
  35. // P_AproxDistance
  36. // Gives an estimation of distance (not exact)
  37. //
  38. fixed_t
  39. P_AproxDistance
  40. ( fixed_t dx,
  41.   fixed_t dy )
  42. {
  43.     dx = abs(dx);
  44.     dy = abs(dy);
  45.     if (dx < dy)
  46. return dx+dy-(dx>>1);
  47.     return dx+dy-(dy>>1);
  48. }
  49. //
  50. // P_PointOnLineSide
  51. // Returns 0 or 1
  52. //
  53. int
  54. P_PointOnLineSide
  55. ( fixed_t x,
  56.   fixed_t y,
  57.   line_t* line )
  58. {
  59.     fixed_t dx;
  60.     fixed_t dy;
  61.     fixed_t left;
  62.     fixed_t right;
  63.     if (!line->dx)
  64.     {
  65. if (x <= line->v1->x)
  66.     return line->dy > 0;
  67. return line->dy < 0;
  68.     }
  69.     if (!line->dy)
  70.     {
  71. if (y <= line->v1->y)
  72.     return line->dx < 0;
  73. return line->dx > 0;
  74.     }
  75.     dx = (x - line->v1->x);
  76.     dy = (y - line->v1->y);
  77.     left = FixedMul ( line->dy>>FRACBITS , dx );
  78.     right = FixedMul ( dy , line->dx>>FRACBITS );
  79.     if (right < left)
  80. return 0; // front side
  81.     return 1; // back side
  82. }
  83. //
  84. // P_BoxOnLineSide
  85. // Considers the line to be infinite
  86. // Returns side 0 or 1, -1 if box crosses the line.
  87. //
  88. int
  89. P_BoxOnLineSide
  90. ( fixed_t* tmbox,
  91.   line_t* ld )
  92. {
  93.     int p1;
  94.     int p2;
  95.     switch (ld->slopetype)
  96.     {
  97.       case ST_HORIZONTAL:
  98. p1 = tmbox[BOXTOP] > ld->v1->y;
  99. p2 = tmbox[BOXBOTTOM] > ld->v1->y;
  100. if (ld->dx < 0)
  101. {
  102.     p1 ^= 1;
  103.     p2 ^= 1;
  104. }
  105. break;
  106.       case ST_VERTICAL:
  107. p1 = tmbox[BOXRIGHT] < ld->v1->x;
  108. p2 = tmbox[BOXLEFT] < ld->v1->x;
  109. if (ld->dy < 0)
  110. {
  111.     p1 ^= 1;
  112.     p2 ^= 1;
  113. }
  114. break;
  115.       case ST_POSITIVE:
  116. p1 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld);
  117. p2 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld);
  118. break;
  119.       case ST_NEGATIVE:
  120. p1 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld);
  121. p2 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld);
  122. break;
  123.     }
  124.     if (p1 == p2)
  125. return p1;
  126.     return -1;
  127. }
  128. //
  129. // P_PointOnDivlineSide
  130. // Returns 0 or 1.
  131. //
  132. int
  133. P_PointOnDivlineSide
  134. ( fixed_t x,
  135.   fixed_t y,
  136.   divline_t* line )
  137. {
  138.     fixed_t dx;
  139.     fixed_t dy;
  140.     fixed_t left;
  141.     fixed_t right;
  142.     if (!line->dx)
  143.     {
  144. if (x <= line->x)
  145.     return line->dy > 0;
  146. return line->dy < 0;
  147.     }
  148.     if (!line->dy)
  149.     {
  150. if (y <= line->y)
  151.     return line->dx < 0;
  152. return line->dx > 0;
  153.     }
  154.     dx = (x - line->x);
  155.     dy = (y - line->y);
  156.     // try to quickly decide by looking at sign bits
  157.     if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 )
  158.     {
  159. if ( (line->dy ^ dx) & 0x80000000 )
  160.     return 1; // (left is negative)
  161. return 0;
  162.     }
  163.     left = FixedMul ( line->dy>>8, dx>>8 );
  164.     right = FixedMul ( dy>>8 , line->dx>>8 );
  165.     if (right < left)
  166. return 0; // front side
  167.     return 1; // back side
  168. }
  169. //
  170. // P_MakeDivline
  171. //
  172. void
  173. P_MakeDivline
  174. ( line_t* li,
  175.   divline_t* dl )
  176. {
  177.     dl->x = li->v1->x;
  178.     dl->y = li->v1->y;
  179.     dl->dx = li->dx;
  180.     dl->dy = li->dy;
  181. }
  182. //
  183. // P_InterceptVector
  184. // Returns the fractional intercept point
  185. // along the first divline.
  186. // This is only called by the addthings
  187. // and addlines traversers.
  188. //
  189. fixed_t
  190. P_InterceptVector
  191. ( divline_t* v2,
  192.   divline_t* v1 )
  193. {
  194. #if 1
  195.     fixed_t frac;
  196.     fixed_t num;
  197.     fixed_t den;
  198.     den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy);
  199.     if (den == 0)
  200. return 0;
  201.     // I_Error ("P_InterceptVector: parallel");
  202.     
  203.     num =
  204. FixedMul ( (v1->x - v2->x)>>8 ,v1->dy )
  205. +FixedMul ( (v2->y - v1->y)>>8, v1->dx );
  206.     frac = FixedDiv (num , den);
  207.     return frac;
  208. #else // UNUSED, float debug.
  209.     float frac;
  210.     float num;
  211.     float den;
  212.     float v1x;
  213.     float v1y;
  214.     float v1dx;
  215.     float v1dy;
  216.     float v2x;
  217.     float v2y;
  218.     float v2dx;
  219.     float v2dy;
  220.     v1x = (float)v1->x/FRACUNIT;
  221.     v1y = (float)v1->y/FRACUNIT;
  222.     v1dx = (float)v1->dx/FRACUNIT;
  223.     v1dy = (float)v1->dy/FRACUNIT;
  224.     v2x = (float)v2->x/FRACUNIT;
  225.     v2y = (float)v2->y/FRACUNIT;
  226.     v2dx = (float)v2->dx/FRACUNIT;
  227.     v2dy = (float)v2->dy/FRACUNIT;
  228.     den = v1dy*v2dx - v1dx*v2dy;
  229.     if (den == 0)
  230. return 0; // parallel
  231.     
  232.     num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx;
  233.     frac = num / den;
  234.     return frac*FRACUNIT;
  235. #endif
  236. }
  237. //
  238. // P_LineOpening
  239. // Sets opentop and openbottom to the window
  240. // through a two sided line.
  241. // OPTIMIZE: keep this precalculated
  242. //
  243. fixed_t opentop;
  244. fixed_t openbottom;
  245. fixed_t openrange;
  246. fixed_t lowfloor;
  247. void P_LineOpening (line_t* linedef)
  248. {
  249.     sector_t* front;
  250.     sector_t* back;
  251.     if (linedef->sidenum[1] == -1)
  252.     {
  253. // single sided line
  254. openrange = 0;
  255. return;
  256.     }
  257.  
  258.     front = linedef->frontsector;
  259.     back = linedef->backsector;
  260.     if (front->ceilingheight < back->ceilingheight)
  261. opentop = front->ceilingheight;
  262.     else
  263. opentop = back->ceilingheight;
  264.     if (front->floorheight > back->floorheight)
  265.     {
  266. openbottom = front->floorheight;
  267. lowfloor = back->floorheight;
  268.     }
  269.     else
  270.     {
  271. openbottom = back->floorheight;
  272. lowfloor = front->floorheight;
  273.     }
  274.     openrange = opentop - openbottom;
  275. }
  276. //
  277. // THING POSITION SETTING
  278. //
  279. //
  280. // P_UnsetThingPosition
  281. // Unlinks a thing from block map and sectors.
  282. // On each position change, BLOCKMAP and other
  283. // lookups maintaining lists ot things inside
  284. // these structures need to be updated.
  285. //
  286. void P_UnsetThingPosition (mobj_t* thing)
  287. {
  288.     int blockx;
  289.     int blocky;
  290.     if ( ! (thing->flags & MF_NOSECTOR) )
  291.     {
  292. // inert things don't need to be in blockmap?
  293. // unlink from subsector
  294. if (thing->snext)
  295.     thing->snext->sprev = thing->sprev;
  296. if (thing->sprev)
  297.     thing->sprev->snext = thing->snext;
  298. else
  299.     thing->subsector->sector->thinglist = thing->snext;
  300.     }
  301.     if ( ! (thing->flags & MF_NOBLOCKMAP) )
  302.     {
  303. // inert things don't need to be in blockmap
  304. // unlink from block map
  305. if (thing->bnext)
  306.     thing->bnext->bprev = thing->bprev;
  307. if (thing->bprev)
  308.     thing->bprev->bnext = thing->bnext;
  309. else
  310. {
  311.     blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;
  312.     blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;
  313.     if (blockx>=0 && blockx < bmapwidth
  314. && blocky>=0 && blocky <bmapheight)
  315.     {
  316. blocklinks[blocky*bmapwidth+blockx] = thing->bnext;
  317.     }
  318. }
  319.     }
  320. }
  321. //
  322. // P_SetThingPosition
  323. // Links a thing into both a block and a subsector
  324. // based on it's x y.
  325. // Sets thing->subsector properly
  326. //
  327. void
  328. P_SetThingPosition (mobj_t* thing)
  329. {
  330.     subsector_t* ss;
  331.     sector_t* sec;
  332.     int blockx;
  333.     int blocky;
  334.     mobj_t** link;
  335.     
  336.     // link into subsector
  337.     ss = R_PointInSubsector (thing->x,thing->y);
  338.     thing->subsector = ss;
  339.     
  340.     if ( ! (thing->flags & MF_NOSECTOR) )
  341.     {
  342. // invisible things don't go into the sector links
  343. sec = ss->sector;
  344. thing->sprev = NULL;
  345. thing->snext = sec->thinglist;
  346. if (sec->thinglist)
  347.     sec->thinglist->sprev = thing;
  348. sec->thinglist = thing;
  349.     }
  350.     
  351.     // link into blockmap
  352.     if ( ! (thing->flags & MF_NOBLOCKMAP) )
  353.     {
  354. // inert things don't need to be in blockmap
  355. blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;
  356. blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;
  357. if (blockx>=0
  358.     && blockx < bmapwidth
  359.     && blocky>=0
  360.     && blocky < bmapheight)
  361. {
  362.     link = &blocklinks[blocky*bmapwidth+blockx];
  363.     thing->bprev = NULL;
  364.     thing->bnext = *link;
  365.     if (*link)
  366. (*link)->bprev = thing;
  367.     *link = thing;
  368. }
  369. else
  370. {
  371.     // thing is off the map
  372.     thing->bnext = thing->bprev = NULL;
  373. }
  374.     }
  375. }
  376. //
  377. // BLOCK MAP ITERATORS
  378. // For each line/thing in the given mapblock,
  379. // call the passed PIT_* function.
  380. // If the function returns false,
  381. // exit with false without checking anything else.
  382. //
  383. //
  384. // P_BlockLinesIterator
  385. // The validcount flags are used to avoid checking lines
  386. // that are marked in multiple mapblocks,
  387. // so increment validcount before the first call
  388. // to P_BlockLinesIterator, then make one or more calls
  389. // to it.
  390. //
  391. boolean
  392. P_BlockLinesIterator
  393. ( int x,
  394.   int y,
  395.   boolean(*func)(line_t*) )
  396. {
  397.     int offset;
  398.     short* list;
  399.     line_t* ld;
  400.     if (x<0
  401. || y<0
  402. || x>=bmapwidth
  403. || y>=bmapheight)
  404.     {
  405. return true;
  406.     }
  407.     
  408.     offset = y*bmapwidth+x;
  409.     offset = *(blockmap+offset);
  410.     for ( list = blockmaplump+offset ; *list != -1 ; list++)
  411.     {
  412. ld = &lines[*list];
  413. if (ld->validcount == validcount)
  414.     continue;  // line has already been checked
  415. ld->validcount = validcount;
  416. if ( !func(ld) )
  417.     return false;
  418.     }
  419.     return true; // everything was checked
  420. }
  421. //
  422. // P_BlockThingsIterator
  423. //
  424. boolean
  425. P_BlockThingsIterator
  426. ( int x,
  427.   int y,
  428.   boolean(*func)(mobj_t*) )
  429. {
  430.     mobj_t* mobj;
  431.     if ( x<0
  432.  || y<0
  433.  || x>=bmapwidth
  434.  || y>=bmapheight)
  435.     {
  436. return true;
  437.     }
  438.     
  439.     for (mobj = blocklinks[y*bmapwidth+x] ;
  440.  mobj ;
  441.  mobj = mobj->bnext)
  442.     {
  443. if (!func( mobj ) )
  444.     return false;
  445.     }
  446.     return true;
  447. }
  448. //
  449. // INTERCEPT ROUTINES
  450. //
  451. intercept_t intercepts[MAXINTERCEPTS];
  452. intercept_t* intercept_p;
  453. divline_t  trace;
  454. boolean  earlyout;
  455. int ptflags;
  456. //
  457. // PIT_AddLineIntercepts.
  458. // Looks for lines in the given block
  459. // that intercept the given trace
  460. // to add to the intercepts list.
  461. //
  462. // A line is crossed if its endpoints
  463. // are on opposite sides of the trace.
  464. // Returns true if earlyout and a solid line hit.
  465. //
  466. boolean
  467. PIT_AddLineIntercepts (line_t* ld)
  468. {
  469.     int s1;
  470.     int s2;
  471.     fixed_t frac;
  472.     divline_t dl;
  473.     // avoid precision problems with two routines
  474.     if ( trace.dx > FRACUNIT*16
  475.  || trace.dy > FRACUNIT*16
  476.  || trace.dx < -FRACUNIT*16
  477.  || trace.dy < -FRACUNIT*16)
  478.     {
  479. s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace);
  480. s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace);
  481.     }
  482.     else
  483.     {
  484. s1 = P_PointOnLineSide (trace.x, trace.y, ld);
  485. s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld);
  486.     }
  487.     
  488.     if (s1 == s2)
  489. return true; // line isn't crossed
  490.     
  491.     // hit the line
  492.     P_MakeDivline (ld, &dl);
  493.     frac = P_InterceptVector (&trace, &dl);
  494.     if (frac < 0)
  495. return true; // behind source
  496.     // try to early out the check
  497.     if (earlyout
  498. && frac < FRACUNIT
  499. && !ld->backsector)
  500.     {
  501. return false; // stop checking
  502.     }
  503.     
  504.     intercept_p->frac = frac;
  505.     intercept_p->isaline = true;
  506.     intercept_p->d.line = ld;
  507.     intercept_p++;
  508.     return true; // continue
  509. }
  510. //
  511. // PIT_AddThingIntercepts
  512. //
  513. boolean PIT_AddThingIntercepts (mobj_t* thing)
  514. {
  515.     fixed_t x1;
  516.     fixed_t y1;
  517.     fixed_t x2;
  518.     fixed_t y2;
  519.     
  520.     int s1;
  521.     int s2;
  522.     
  523.     boolean tracepositive;
  524.     divline_t dl;
  525.     
  526.     fixed_t frac;
  527.     tracepositive = (trace.dx ^ trace.dy)>0;
  528.     // check a corner to corner crossection for hit
  529.     if (tracepositive)
  530.     {
  531. x1 = thing->x - thing->radius;
  532. y1 = thing->y + thing->radius;
  533. x2 = thing->x + thing->radius;
  534. y2 = thing->y - thing->radius;
  535.     }
  536.     else
  537.     {
  538. x1 = thing->x - thing->radius;
  539. y1 = thing->y - thing->radius;
  540. x2 = thing->x + thing->radius;
  541. y2 = thing->y + thing->radius;
  542.     }
  543.     
  544.     s1 = P_PointOnDivlineSide (x1, y1, &trace);
  545.     s2 = P_PointOnDivlineSide (x2, y2, &trace);
  546.     if (s1 == s2)
  547. return true; // line isn't crossed
  548.     dl.x = x1;
  549.     dl.y = y1;
  550.     dl.dx = x2-x1;
  551.     dl.dy = y2-y1;
  552.     
  553.     frac = P_InterceptVector (&trace, &dl);
  554.     if (frac < 0)
  555. return true; // behind source
  556.     intercept_p->frac = frac;
  557.     intercept_p->isaline = false;
  558.     intercept_p->d.thing = thing;
  559.     intercept_p++;
  560.     return true; // keep going
  561. }
  562. //
  563. // P_TraverseIntercepts
  564. // Returns true if the traverser function returns true
  565. // for all lines.
  566. // 
  567. boolean
  568. P_TraverseIntercepts
  569. ( traverser_t func,
  570.   fixed_t maxfrac )
  571. {
  572.     int count;
  573.     fixed_t dist;
  574.     intercept_t* scan;
  575.     intercept_t* in;
  576.     count = intercept_p - intercepts;
  577.     
  578.     in = 0; // shut up compiler warning
  579.     while (count--)
  580.     {
  581. dist = MAXINT;
  582. for (scan = intercepts ; scan<intercept_p ; scan++)
  583. {
  584.     if (scan->frac < dist)
  585.     {
  586. dist = scan->frac;
  587. in = scan;
  588.     }
  589. }
  590. if (dist > maxfrac)
  591.     return true; // checked everything in range
  592. #if 0  // UNUSED
  593.     {
  594. // don't check these yet, there may be others inserted
  595. in = scan = intercepts;
  596. for ( scan = intercepts ; scan<intercept_p ; scan++)
  597.     if (scan->frac > maxfrac)
  598. *in++ = *scan;
  599. intercept_p = in;
  600. return false;
  601.     }
  602. #endif
  603.         if ( !func (in) )
  604.     return false; // don't bother going farther
  605. in->frac = MAXINT;
  606.     }
  607.     return true; // everything was traversed
  608. }
  609. //
  610. // P_PathTraverse
  611. // Traces a line from x1,y1 to x2,y2,
  612. // calling the traverser function for each.
  613. // Returns true if the traverser function returns true
  614. // for all lines.
  615. //
  616. boolean
  617. P_PathTraverse
  618. ( fixed_t x1,
  619.   fixed_t y1,
  620.   fixed_t x2,
  621.   fixed_t y2,
  622.   int flags,
  623.   boolean (*trav) (intercept_t *))
  624. {
  625.     fixed_t xt1;
  626.     fixed_t yt1;
  627.     fixed_t xt2;
  628.     fixed_t yt2;
  629.     
  630.     fixed_t xstep;
  631.     fixed_t ystep;
  632.     
  633.     fixed_t partial;
  634.     
  635.     fixed_t xintercept;
  636.     fixed_t yintercept;
  637.     
  638.     int mapx;
  639.     int mapy;
  640.     
  641.     int mapxstep;
  642.     int mapystep;
  643.     int count;
  644.     earlyout = flags & PT_EARLYOUT;
  645.     validcount++;
  646.     intercept_p = intercepts;
  647.     if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
  648. x1 += FRACUNIT; // don't side exactly on a line
  649.     
  650.     if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0)
  651. y1 += FRACUNIT; // don't side exactly on a line
  652.     trace.x = x1;
  653.     trace.y = y1;
  654.     trace.dx = x2 - x1;
  655.     trace.dy = y2 - y1;
  656.     x1 -= bmaporgx;
  657.     y1 -= bmaporgy;
  658.     xt1 = x1>>MAPBLOCKSHIFT;
  659.     yt1 = y1>>MAPBLOCKSHIFT;
  660.     x2 -= bmaporgx;
  661.     y2 -= bmaporgy;
  662.     xt2 = x2>>MAPBLOCKSHIFT;
  663.     yt2 = y2>>MAPBLOCKSHIFT;
  664.     if (xt2 > xt1)
  665.     {
  666. mapxstep = 1;
  667. partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1));
  668. ystep = FixedDiv (y2-y1,abs(x2-x1));
  669.     }
  670.     else if (xt2 < xt1)
  671.     {
  672. mapxstep = -1;
  673. partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1);
  674. ystep = FixedDiv (y2-y1,abs(x2-x1));
  675.     }
  676.     else
  677.     {
  678. mapxstep = 0;
  679. partial = FRACUNIT;
  680. ystep = 256*FRACUNIT;
  681.     }
  682.     yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep);
  683.     if (yt2 > yt1)
  684.     {
  685. mapystep = 1;
  686. partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1));
  687. xstep = FixedDiv (x2-x1,abs(y2-y1));
  688.     }
  689.     else if (yt2 < yt1)
  690.     {
  691. mapystep = -1;
  692. partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1);
  693. xstep = FixedDiv (x2-x1,abs(y2-y1));
  694.     }
  695.     else
  696.     {
  697. mapystep = 0;
  698. partial = FRACUNIT;
  699. xstep = 256*FRACUNIT;
  700.     }
  701.     xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep);
  702.     
  703.     // Step through map blocks.
  704.     // Count is present to prevent a round off error
  705.     // from skipping the break.
  706.     mapx = xt1;
  707.     mapy = yt1;
  708.     for (count = 0 ; count < 64 ; count++)
  709.     {
  710. if (flags & PT_ADDLINES)
  711. {
  712.     if (!P_BlockLinesIterator (mapx, mapy,PIT_AddLineIntercepts))
  713. return false; // early out
  714. }
  715. if (flags & PT_ADDTHINGS)
  716. {
  717.     if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts))
  718. return false; // early out
  719. }
  720. if (mapx == xt2
  721.     && mapy == yt2)
  722. {
  723.     break;
  724. }
  725. if ( (yintercept >> FRACBITS) == mapy)
  726. {
  727.     yintercept += ystep;
  728.     mapx += mapxstep;
  729. }
  730. else if ( (xintercept >> FRACBITS) == mapx)
  731. {
  732.     xintercept += xstep;
  733.     mapy += mapystep;
  734. }
  735.     }
  736.     // go through the sorted list
  737.     return P_TraverseIntercepts ( trav, FRACUNIT );
  738. }