DOOM64-RE

DOOM 64 Reverse Engineering
Log | Files | Refs | README | LICENSE

p_move.c (15996B)


      1 #include "doomdef.h"
      2 #include "p_local.h"
      3 
      4 /*================== */
      5 /* */
      6 /* out */
      7 /* */
      8 /*================== */
      9 
     10 extern	mobj_t  *tmthing;		// 800A56B0
     11 extern	fixed_t  tmx, tmy;		// 800A56B4, 800A56B8
     12 extern	boolean  checkposonly;	// 800A56C8
     13 
     14 /*================== */
     15 /* */
     16 /* in */
     17 /* */
     18 /*================== */
     19 
     20 boolean trymove2;		// 800A5D80	/* Result from P_TryMove2 */
     21 boolean floatok;		// 800A5D84	/* if true, move would be ok if within tmfloorz - tmceilingz */
     22 fixed_t tmfloorz;		// 800A5D88	/* Current floor z for P_TryMove2 */
     23 fixed_t tmceilingz;		// 800A5D8C	/* Current ceiling z for P_TryMove2 */
     24 mobj_t *movething;		// 800A5D98  /* Either a skull/missile target or a special pickup */
     25 line_t *blockline;		// 800A5D9C	/* Might be a door that can be opened */
     26 
     27 fixed_t		oldx, oldy;	// 800A5DA0, 800A5DA4
     28 fixed_t		tmbbox[4];  //
     29 int			tmflags;	// 800A5DB8
     30 fixed_t		tmdropoffz;	// 800A5D90 /* Lowest point contacted */
     31 subsector_t	*newsubsec;	// 800A5D94 /* Dest subsector */
     32 
     33 //PSX NEW
     34 line_t *thingspec[8];		// 800A5DE0
     35 int		numthingspec;		// 800A5DE0
     36 
     37 /*
     38 ===================
     39 =
     40 = P_TryMove2
     41 =
     42 = Attempt to move to a new position, crossing special lines unless MF_TELEPORT
     43 = is set
     44 =
     45 ===================
     46 */
     47 
     48 void P_TryMove2(void) // 80019980
     49 {
     50 	int		side;
     51 	int		oldside;
     52 	line_t	*line;
     53 
     54 	trymove2 = false;		// until proven otherwise
     55 	floatok = false;
     56 
     57 	oldx = tmthing->x;
     58 	oldy = tmthing->y;
     59 
     60 	PM_CheckPosition();
     61 
     62 	if (checkposonly)
     63     {
     64 		checkposonly = false;
     65 		return;
     66 	}
     67 
     68 	if (!trymove2)
     69 		return;
     70 
     71 	if (!(tmthing->flags & MF_NOCLIP))
     72     {
     73 		trymove2 = false;
     74 
     75 		if (tmceilingz - tmfloorz < tmthing->height)
     76 			return;			// doesn't fit
     77 		floatok = true;
     78 		if ( !(tmthing->flags&MF_TELEPORT) && tmceilingz - tmthing->z < tmthing->height)
     79 			return;			// mobj must lower itself to fit
     80 		if ( !(tmthing->flags&MF_TELEPORT) && tmfloorz - tmthing->z > 24*FRACUNIT )
     81 			return;			// too big a step up
     82 		if ( !(tmthing->flags&(MF_DROPOFF|MF_FLOAT)) && tmfloorz - tmdropoffz > 24*FRACUNIT )
     83 			return;			// don't stand over a dropoff
     84 	}
     85 
     86 	//
     87 	// the move is ok, so link the thing into its new position
     88 	//
     89 	P_UnsetThingPosition(tmthing);
     90 
     91 	tmthing->floorz = tmfloorz;
     92 	tmthing->ceilingz = tmceilingz;
     93 	tmthing->x = tmx;
     94 	tmthing->y = tmy;
     95 
     96 	P_SetThingPosition(tmthing);
     97 
     98 	if (!(tmthing->flags & (MF_NOCLIP | MF_TELEPORT)))
     99 	{
    100 		while (numthingspec > 0)
    101 		{
    102 			numthingspec--;
    103 			line = thingspec[numthingspec];
    104 
    105 			side = P_PointOnLineSide(tmthing->x, tmthing->y, line);
    106 			oldside = P_PointOnLineSide(oldx, oldy, line);
    107 
    108 			if (side != oldside)
    109             {
    110                 if (!(line->flags & ML_TRIGGERFRONT) || (side))
    111                 {
    112                     P_UseSpecialLine(line, tmthing);
    113                 }
    114             }
    115 		}
    116 	}
    117 
    118 	trymove2 = true;
    119 
    120 	return;
    121 }
    122 
    123 /*
    124 ==================
    125 =
    126 = P_PointOnLineSide
    127 =
    128 = Returns 0 or 1
    129 ==================
    130 */
    131 
    132 int P_PointOnLineSide (fixed_t x, fixed_t y, line_t *line) // 80019C24
    133 {
    134 	fixed_t	dx,dy;
    135 	fixed_t	left, right;
    136 
    137 	if (!line->dx)
    138 	{
    139 		if (x <= line->v1->x)
    140 			return line->dy > 0;
    141 		return line->dy < 0;
    142 	}
    143 	if (!line->dy)
    144 	{
    145 		if (y <= line->v1->y)
    146 			return line->dx < 0;
    147 		return line->dx > 0;
    148 	}
    149 
    150 	dx = (x - line->v1->x);
    151 	dy = (y - line->v1->y);
    152 
    153 	left = (line->dy>>16) * (dx>>16);
    154 	right = (dy>>16) * (line->dx>>16);
    155 
    156 	if (right < left)
    157 		return 0;		/* front side */
    158 	return 1;			/* back side */
    159 }
    160 
    161 #if 0
    162 static boolean PM_CrossCheck(line_t *ld)
    163 {
    164 	if (PM_BoxCrossLine (ld))	{
    165 		if (!PIT_CheckLine(ld)) {
    166 			return true;
    167 		}
    168 	}
    169 	return false;
    170 }
    171 
    172 /*
    173 ==================
    174 =
    175 = PM_PointOnLineSide
    176 = Exclusive Psx Doom
    177 =
    178 = Returns 0 or 1
    179 =
    180 ==================
    181 */
    182 
    183 int PM_PointOnLineSide(fixed_t x, fixed_t y, line_t *line)//L8001EB8C()
    184 {
    185 	fixed_t dx, dy;
    186 	fixed_t left, right;
    187 
    188 	dx = (x - line->v1->x);
    189 	dy = (y - line->v1->y);
    190 
    191 	left  = (line->dy >> 16) * (dx >> 16);
    192 	right = (dy >> 16) *(line->dx >> 16);
    193 
    194 	if (right < left)
    195 		return 0; /* front side */
    196 	return 1;    /* back side */
    197 }
    198 #endif
    199 
    200 /*
    201 ===============================================================================
    202 
    203 						THING POSITION SETTING
    204 
    205 ===============================================================================
    206 */
    207 
    208 /*
    209 ===================
    210 =
    211 = P_UnsetThingPosition
    212 =
    213 = Unlinks a thing from block map and sectors
    214 =
    215 ===================
    216 */
    217 
    218 void P_UnsetThingPosition (mobj_t *thing)//L8001C768()
    219 {
    220 	int blockx, blocky;
    221 
    222 	if (!(thing->flags & MF_NOSECTOR))
    223 	{	/* inert things don't need to be in blockmap */
    224 		/* unlink from subsector */
    225 		if (thing->snext)
    226 			thing->snext->sprev = thing->sprev;
    227 		if (thing->sprev)
    228 			thing->sprev->snext = thing->snext;
    229 		else
    230 			thing->subsector->sector->thinglist = thing->snext;
    231 	}
    232 
    233 	if (!(thing->flags & MF_NOBLOCKMAP))
    234 	{	/* inert things don't need to be in blockmap */
    235 		/* unlink from block map */
    236 		if (thing->bnext)
    237 			thing->bnext->bprev = thing->bprev;
    238 		if (thing->bprev)
    239 			thing->bprev->bnext = thing->bnext;
    240 		else
    241 		{
    242 			blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;
    243 			blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;
    244 
    245 			// Prevent buffer overflow if the map object is out of bounds.
    246             // This is part of the fix for the famous 'linedef deletion' bug.
    247             // From PsyDoom (StationDoom) by BodbDearg
    248 			#if FIX_LINEDEFS_DELETION == 1
    249             if (blockx>=0 && blockx <bmapwidth
    250              && blocky>=0 && blocky <bmapheight)
    251             {
    252                 blocklinks[blocky*bmapwidth+blockx] = thing->bnext;
    253             }
    254             #else
    255                 blocklinks[blocky*bmapwidth+blockx] = thing->bnext;
    256 			#endif
    257 		}
    258 	}
    259 }
    260 
    261 
    262 /*
    263 ===================
    264 =
    265 = P_SetThingPosition
    266 =
    267 = Links a thing into both a block and a subsector based on it's x y
    268 = Sets thing->subsector properly
    269 =
    270 ===================
    271 */
    272 
    273 void P_SetThingPosition (mobj_t *thing) // 80019E20
    274 {
    275 	subsector_t  *ss;
    276     sector_t     *sec;
    277     int           blockx, blocky;
    278     mobj_t      **link;
    279 
    280     /* */
    281     /* link into subsector */
    282     /* */
    283     ss = R_PointInSubsector (thing->x,thing->y);
    284     thing->subsector = ss;
    285     if(!(thing->flags & MF_NOSECTOR))
    286     {
    287         /* invisible things don't go into the sector links */
    288         sec = ss->sector;
    289 
    290         thing->sprev = NULL;
    291         thing->snext = sec->thinglist;
    292         if(sec->thinglist)
    293          sec->thinglist->sprev = thing;
    294         sec->thinglist = thing;
    295     }
    296 
    297     /* */
    298     /* link into blockmap */
    299     /* */
    300     if(!(thing->flags & MF_NOBLOCKMAP))
    301     {
    302         /* inert things don't need to be in blockmap */
    303         blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;
    304         blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;
    305         if(blockx >= 0 && blockx < bmapwidth && blocky >= 0 && blocky < bmapheight)
    306         {
    307             link = &blocklinks[blocky*bmapwidth+blockx];
    308             thing->bprev = NULL;
    309             thing->bnext = *link;
    310             if (*link)
    311                 (*link)->bprev = thing;
    312             *link = thing;
    313         }
    314         else
    315         {
    316             /* thing is off the map */
    317             thing->bnext = thing->bprev = NULL;
    318         }
    319     }
    320 }
    321 
    322 /*
    323 ==================
    324 =
    325 = PM_CheckPosition
    326 =
    327 = This is purely informative, nothing is modified (except things picked up)
    328 
    329 in:
    330 tmthing		a mobj_t (can be valid or invalid)
    331 tmx,tmy		a position to be checked (doesn't need relate to the mobj_t->x,y)
    332 
    333 out:
    334 
    335 newsubsec
    336 floorz
    337 ceilingz
    338 tmdropoffz		the lowest point contacted (monsters won't move to a dropoff)
    339 movething
    340 
    341 ==================
    342 */
    343 
    344 void PM_CheckPosition (void) // 80019F50
    345 {
    346 	int			xl,xh,yl,yh,bx,by;
    347 
    348 	tmflags = tmthing->flags;
    349 
    350 	tmbbox[BOXTOP] = tmy + tmthing->radius;
    351 	tmbbox[BOXBOTTOM] = tmy - tmthing->radius;
    352 	tmbbox[BOXRIGHT] = tmx + tmthing->radius;
    353 	tmbbox[BOXLEFT] = tmx - tmthing->radius;
    354 
    355 	newsubsec = R_PointInSubsector(tmx,tmy);
    356 
    357 	//
    358 	// the base floor / ceiling is from the subsector that contains the
    359 	// point.  Any contacted lines the step closer together will adjust them
    360 	//
    361 	tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
    362 	tmceilingz = newsubsec->sector->ceilingheight;
    363 
    364 	++validcount;
    365 
    366 	numthingspec = 0;//PSX
    367 	movething = NULL;
    368 	blockline = NULL;
    369 
    370 	if (tmflags & MF_NOCLIP)
    371 	{
    372 		trymove2 = true;
    373 		return;
    374 	}
    375 
    376 	//
    377 	// check things first, possibly picking things up
    378 	// the bounding box is extended by MAXRADIUS because mobj_ts are grouped
    379 	// into mapblocks based on their origin point, and can overlap into adjacent
    380 	// blocks by up to MAXRADIUS units
    381 	//
    382 	// [D64] no use MAXRADIUS
    383 	//
    384 	xl = (tmbbox[BOXLEFT] - bmaporgx/* - MAXRADIUS*/)>>MAPBLOCKSHIFT;
    385 	xh = (tmbbox[BOXRIGHT] - bmaporgx/* + MAXRADIUS*/)>>MAPBLOCKSHIFT;
    386 	yl = (tmbbox[BOXBOTTOM] - bmaporgy/* - MAXRADIUS*/)>>MAPBLOCKSHIFT;
    387 	yh = (tmbbox[BOXTOP] - bmaporgy/* + MAXRADIUS*/)>>MAPBLOCKSHIFT;
    388 
    389 	if (xl<0)
    390 		xl = 0;
    391 	if (yl<0)
    392 		yl = 0;
    393 	if (xh>= bmapwidth)
    394 		xh = bmapwidth -1;
    395 	if (yh>= bmapheight)
    396 		yh = bmapheight -1;
    397 
    398 	for (bx = xl; bx <= xh; bx++)
    399 	{
    400 		for (by = yl; by <= yh; by++)
    401 		{
    402 			if (!PM_BlockThingsIterator(bx, by))
    403 			{
    404 				trymove2 = false;
    405 				return;
    406 			}
    407 		}
    408 	}
    409 
    410 	//
    411 	// check lines
    412 	//
    413 	xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
    414 	xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
    415 	yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
    416 	yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
    417 
    418 	if (xl<0)
    419 		xl = 0;
    420 	if (yl<0)
    421 		yl = 0;
    422 	if (xh>= bmapwidth)
    423 		xh = bmapwidth -1;
    424 	if (yh>= bmapheight)
    425 		yh = bmapheight -1;
    426 
    427 	for (bx = xl; bx <= xh; bx++)
    428 	{
    429 		for (by = yl; by <= yh; by++)
    430 		{
    431 			if (!PM_BlockLinesIterator(bx, by))
    432 			{
    433 				trymove2 = false;
    434 				return;
    435 			}
    436 		}
    437 	}
    438 
    439 	trymove2 = true;
    440 	return;
    441 }
    442 
    443 //=============================================================================
    444 
    445 
    446 /*
    447 =================
    448 =
    449 = PM_BoxCrossLine
    450 =
    451 =================
    452 */
    453 boolean PM_BoxCrossLine (line_t *ld) // 8001A280
    454 {
    455 	boolean		side1, side2;
    456 
    457 	if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
    458 	||	tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
    459 	||	tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
    460 	||	tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] )
    461 		return false;
    462 
    463     switch(ld->slopetype)
    464     {
    465     case ST_HORIZONTAL:
    466         side1 = (ld->bbox[BOXTOP] < tmbbox[BOXTOP]);
    467         side2 = (ld->bbox[BOXTOP] < tmbbox[BOXBOTTOM]);
    468         break;
    469 
    470     case ST_VERTICAL:
    471         side1 = (ld->bbox[BOXLEFT] < tmbbox[BOXRIGHT]);
    472         side2 = (ld->bbox[BOXLEFT] < tmbbox[BOXLEFT]);
    473         break;
    474 
    475     case ST_POSITIVE:
    476         side1 = P_PointOnLineSide(tmbbox[BOXLEFT], tmbbox[BOXTOP], ld);
    477         side2 = P_PointOnLineSide(tmbbox[BOXRIGHT], tmbbox[BOXBOTTOM], ld);
    478         break;
    479 
    480     case ST_NEGATIVE:
    481         side1 = P_PointOnLineSide(tmbbox[BOXRIGHT], tmbbox[BOXTOP], ld);
    482         side2 = P_PointOnLineSide(tmbbox[BOXLEFT], tmbbox[BOXBOTTOM], ld);
    483         break;
    484 
    485     default:
    486         break;
    487     }
    488 
    489     return (0 < (side1 ^ side2));
    490 }
    491 
    492 //=============================================================================
    493 
    494 
    495 /*
    496 ==================
    497 =
    498 = PIT_CheckLine
    499 =
    500 = Adjusts tmfloorz and tmceilingz as lines are contacted
    501 ==================
    502 */
    503 
    504 boolean PIT_CheckLine (line_t *ld) // 8001A3DC
    505 {
    506 	fixed_t		pm_opentop, pm_openbottom;
    507 	fixed_t		pm_lowfloor;
    508 	sector_t	*front, *back;
    509 
    510 	// a line has been hit
    511 
    512 	/*
    513 	=
    514 	= The moving thing's destination position will cross the given line.
    515 	= If this should not be allowed, return false.
    516 	*/
    517 	if (!ld->backsector)
    518 		return false;		// one sided line
    519 
    520 	if (!(tmthing->flags & MF_MISSILE) )
    521 	{
    522 		if ( ld->flags & ML_BLOCKING )
    523 			return false;		// explicitly blocking everything
    524 		if ( !tmthing->player && ld->flags & ML_BLOCKMONSTERS )
    525 			return false;		// block monsters only
    526 	}
    527 
    528 	front = ld->frontsector;
    529 	back = ld->backsector;
    530 
    531 	if (front->ceilingheight == front->floorheight
    532 	|| back->ceilingheight == back->floorheight)
    533 	{
    534 		blockline = ld;
    535 		return false;			// probably a closed door
    536 	}
    537 
    538 	if (front->ceilingheight < back->ceilingheight)
    539 		pm_opentop = front->ceilingheight;
    540 	else
    541 		pm_opentop = back->ceilingheight;
    542 
    543 	if (front->floorheight > back->floorheight)
    544 	{
    545 		pm_openbottom = front->floorheight;
    546 		pm_lowfloor = back->floorheight;
    547 	}
    548 	else
    549 	{
    550 		pm_openbottom = back->floorheight;
    551 		pm_lowfloor = front->floorheight;
    552 	}
    553 
    554 	// adjust floor / ceiling heights
    555 	if (pm_opentop < tmceilingz)
    556 		tmceilingz = pm_opentop;
    557 	if (pm_openbottom > tmfloorz)
    558 		tmfloorz = pm_openbottom;
    559 	if (pm_lowfloor < tmdropoffz)
    560 		tmdropoffz = pm_lowfloor;
    561 
    562 	// if contacted a special line, add it to the list
    563     if(ld->special & MLU_CROSS)
    564 	{
    565 	    //New Psx Doom
    566 		if (numthingspec < MAXTHINGSPEC)
    567 		{
    568 			thingspec[numthingspec] = ld;
    569 			numthingspec++;
    570 		}
    571 	}
    572 
    573 	return true;
    574 }
    575 
    576 /*
    577 ==================
    578 =
    579 = PIT_CheckThing
    580 =
    581 ==================
    582 */
    583 
    584 boolean PIT_CheckThing(mobj_t *thing) // 8001A560
    585 {
    586 	fixed_t blockdist;
    587 	fixed_t x, y;
    588     fixed_t rx, ry;
    589 
    590     if (thing == tmthing)
    591         return true;        // don't clip against self
    592 
    593 	if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) ))
    594 		return true;
    595 
    596 	blockdist = thing->radius + tmthing->radius;
    597 
    598 	/*delta = thing->x - tmx;
    599 	if (delta < 0)
    600 		delta = -delta;
    601 	if (delta >= blockdist)
    602 		return true;		// didn't hit it
    603 
    604 	delta = thing->y - tmy;
    605 	if (delta < 0)
    606 		delta = -delta;
    607 	if (delta >= blockdist)
    608 		return true;		// didn't hit it
    609 
    610 	if (thing == tmthing)
    611 		return true;		// don't clip against self*/
    612 
    613     // [d64]: different logic versus Jaguar Doom
    614     x = abs(thing->x - tmx);
    615     y = abs(thing->y - tmy);
    616 
    617     rx = blockdist - x;
    618     ry = blockdist - x;
    619 
    620     if(!(x < y))
    621     {
    622         if(((rx - y) + (y >> 1)) <= 0)
    623             return true; // didn't hit it
    624     }
    625     else
    626     {
    627         if(((ry - y) + (x >> 1)) <= 0)
    628             return true; // didn't hit it
    629     }
    630 
    631 	//
    632 	// check for skulls slamming into things
    633 	//
    634 	if (tmthing->flags & MF_SKULLFLY)
    635 	{
    636 		movething = thing;
    637 		return false;		// stop moving
    638 	}
    639 
    640 	//
    641 	// missiles can hit other things
    642 	//
    643 	if (tmthing->flags & MF_MISSILE)
    644 	{
    645 		// see if it went over / under
    646 		if (tmthing->z > thing->z + thing->height)
    647 			return true;		// overhead
    648 		if (tmthing->z+tmthing->height < thing->z)
    649 			return true;		// underneath
    650 		if (tmthing->target->type == thing->type) // don't hit same species as originator
    651 		{
    652 			if (thing == tmthing->target)
    653 				return true;
    654 			if (thing->type != MT_PLAYER) // let players missile other players
    655 				return false;	// explode, but do no damage
    656 		}
    657 		if (! (thing->flags & MF_SHOOTABLE) )
    658 			return !(thing->flags & MF_SOLID);		// didn't do any damage
    659 
    660 		// damage / explode
    661 		movething = thing;
    662 		return false;			// don't traverse any more
    663 	}
    664 
    665 	//
    666 	// check for special pickup
    667 	//
    668 	if ((thing->flags&MF_SPECIAL) && (tmflags&MF_PICKUP) )
    669 	{
    670 		movething = thing;
    671 		return true;
    672 	}
    673 
    674 	return !(thing->flags & MF_SOLID);
    675 }
    676 
    677 /*
    678 ===============================================================================
    679 
    680 BLOCK MAP ITERATORS
    681 
    682 For each line/thing in the given mapblock, call the passed function.
    683 If the function returns false, exit with false without checking anything else.
    684 
    685 ===============================================================================
    686 */
    687 
    688 /*
    689 ==================
    690 =
    691 = PM_BlockLinesIterator
    692 = Exclusive Psx Doom / Doom 64
    693 =
    694 = The validcount flags are used to avoid checking lines
    695 = that are marked in multiple mapblocks, so increment validcount before
    696 = the first call to PM_BlockLinesIterator, then make one or more calls to it
    697 =
    698 ==================
    699 */
    700 
    701 boolean PM_BlockLinesIterator(int x, int y) // 8001A710
    702 {
    703 	int     offset;
    704 	short  *list;
    705 	line_t *ld;
    706 
    707 	offset = (y*bmapwidth)+x;
    708 	offset = *(blockmap + offset);
    709 
    710 	for (list = blockmaplump + offset; *list != -1; list++)
    711 	{
    712 		ld = &lines[*list];
    713 		if (ld->validcount == validcount)
    714 			continue; /* line has already been checked */
    715 		ld->validcount = validcount;
    716 
    717 		if (PM_BoxCrossLine(ld))
    718 		{
    719 			if (!PIT_CheckLine(ld))
    720 				return false;
    721 		}
    722 	}
    723 
    724 	return true; /* everything was checked */
    725 }
    726 
    727 /*
    728 ==================
    729 =
    730 = PM_BlockThingsIterator
    731 = Exclusive Psx Doom / Doom 64
    732 =
    733 ==================
    734 */
    735 
    736 boolean PM_BlockThingsIterator(int x, int y) // 8001A810
    737 {
    738 	mobj_t *mobj;
    739 
    740 	for (mobj = blocklinks[y * bmapwidth + x]; mobj; mobj = mobj->bnext)
    741 	{
    742 		if (!PIT_CheckThing(mobj))
    743 			return false;
    744 	}
    745 
    746 	return true;
    747 }