=== DOOM - id Tech 1 - p_enemy.c @ 363 ========================================================== rf: https://github.com/id-Software/DOOM/blob/master/linuxdoom-1.10/p_enemy.c void P_NewChaseDir (mobj_t* actor) { fixed_t deltax; fixed_t deltay; dirtype_t d[3]; int tdir; dirtype_t olddir; dirtype_t turnaround; if (!actor->target) I_Error ("P_NewChaseDir: called with no target"); olddir = actor->movedir; turnaround=opposite[olddir]; deltax = actor->target->x - actor->x; deltay = actor->target->y - actor->y; if (deltax>10*FRACUNIT) d[1]= DI_EAST; else if (deltax<-10*FRACUNIT) d[1]= DI_WEST; else d[1]=DI_NODIR; if (deltay<-10*FRACUNIT) d[2]= DI_SOUTH; else if (deltay>10*FRACUNIT) d[2]= DI_NORTH; else d[2]=DI_NODIR; // try direct route if (d[1] != DI_NODIR && d[2] != DI_NODIR) { actor->movedir = diags[((deltay<0)<<1)+(deltax>0)]; if (actor->movedir != turnaround && P_TryWalk(actor)) return; } // try other directions if (P_Random() > 200 || abs(deltay)>abs(deltax)) { tdir=d[1]; d[1]=d[2]; d[2]=tdir; } if (d[1]==turnaround) d[1]=DI_NODIR; if (d[2]==turnaround) d[2]=DI_NODIR; if (d[1]!=DI_NODIR) { actor->movedir = d[1]; if (P_TryWalk(actor)) { // either moved forward or attacked return; } } if (d[2]!=DI_NODIR) { actor->movedir =d[2]; if (P_TryWalk(actor)) return; } // there is no direct path to the player, // so pick another direction. if (olddir!=DI_NODIR) { actor->movedir =olddir; if (P_TryWalk(actor)) return; } // randomly determine direction of search if (P_Random()&1) { for ( tdir=DI_EAST; tdir<=DI_SOUTHEAST; tdir++ ) { if (tdir!=turnaround) { actor->movedir =tdir; if ( P_TryWalk(actor) ) return; } } } else { for ( tdir=DI_SOUTHEAST; tdir != (DI_EAST-1); tdir-- ) { if (tdir!=turnaround) { actor->movedir =tdir; if ( P_TryWalk(actor) ) return; } } } if (turnaround != DI_NODIR) { actor->movedir =turnaround; if ( P_TryWalk(actor) ) return; } actor->movedir = DI_NODIR; // can not move } === QUAKE - id Tech 2 - sv_move.c @ 284 ========================================================= rf: https://github.com/id-Software/Quake/blob/master/WinQuake/sv_move.c /* ================ SV_NewChaseDir ================ */ #define DI_NODIR -1 void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist) { float deltax,deltay; float d[3]; float tdir, olddir, turnaround; olddir = anglemod( (int)(actor->v.ideal_yaw/45)*45 ); turnaround = anglemod(olddir - 180); deltax = enemy->v.origin[0] - actor->v.origin[0]; deltay = enemy->v.origin[1] - actor->v.origin[1]; if (deltax>10) d[1]= 0; else if (deltax<-10) d[1]= 180; else d[1]= DI_NODIR; if (deltay<-10) d[2]= 270; else if (deltay>10) d[2]= 90; else d[2]= DI_NODIR; // try direct route if (d[1] != DI_NODIR && d[2] != DI_NODIR) { if (d[1] == 0) tdir = d[2] == 90 ? 45 : 315; else tdir = d[2] == 90 ? 135 : 215; if (tdir != turnaround && SV_StepDirection(actor, tdir, dist)) return; } // try other directions if ( ((rand()&3) & 1) || abs(deltay)>abs(deltax)) { tdir=d[1]; d[1]=d[2]; d[2]=tdir; } if (d[1]!=DI_NODIR && d[1]!=turnaround && SV_StepDirection(actor, d[1], dist)) return; if (d[2]!=DI_NODIR && d[2]!=turnaround && SV_StepDirection(actor, d[2], dist)) return; /* there is no direct path to the player, so pick another direction */ if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist)) return; if (rand()&1) /*randomly determine direction of search*/ { for (tdir=0 ; tdir<=315 ; tdir += 45) if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) ) return; } else { for (tdir=315 ; tdir >=0 ; tdir -= 45) if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) ) return; } if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) ) return; actor->v.ideal_yaw = olddir; // can't move // if a bridge was pulled out from underneath a monster, it may not have // a valid standing position at all if (!SV_CheckBottom (actor)) SV_FixCheckBottom (actor); } === QUAKE 2 - id Tech 2 - m_move.c @ 403 ======================================================== rf: https://github.com/id-Software/Quake-2/blob/master/game/m_move.c /* ================ SV_NewChaseDir ================ */ #define DI_NODIR -1 void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist) { float deltax,deltay; float d[3]; float tdir, olddir, turnaround; //FIXME: how did we get here with no enemy if (!enemy) return; olddir = anglemod( (int)(actor->ideal_yaw/45)*45 ); turnaround = anglemod(olddir - 180); deltax = enemy->s.origin[0] - actor->s.origin[0]; deltay = enemy->s.origin[1] - actor->s.origin[1]; if (deltax>10) d[1]= 0; else if (deltax<-10) d[1]= 180; else d[1]= DI_NODIR; if (deltay<-10) d[2]= 270; else if (deltay>10) d[2]= 90; else d[2]= DI_NODIR; // try direct route if (d[1] != DI_NODIR && d[2] != DI_NODIR) { if (d[1] == 0) tdir = d[2] == 90 ? 45 : 315; else tdir = d[2] == 90 ? 135 : 215; if (tdir != turnaround && SV_StepDirection(actor, tdir, dist)) return; } // try other directions if ( ((rand()&3) & 1) || abs(deltay)>abs(deltax)) { tdir=d[1]; d[1]=d[2]; d[2]=tdir; } if (d[1]!=DI_NODIR && d[1]!=turnaround && SV_StepDirection(actor, d[1], dist)) return; if (d[2]!=DI_NODIR && d[2]!=turnaround && SV_StepDirection(actor, d[2], dist)) return; /* there is no direct path to the player, so pick another direction */ if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist)) return; if (rand()&1) /*randomly determine direction of search*/ { for (tdir=0 ; tdir<=315 ; tdir += 45) if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) ) return; } else { for (tdir=315 ; tdir >=0 ; tdir -= 45) if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) ) return; } if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) ) return; actor->ideal_yaw = olddir; // can't move // if a bridge was pulled out from underneath a monster, it may not have // a valid standing position at all if (!M_CheckBottom (actor)) SV_FixCheckBottom (actor); } === QUAKE 3 - id Tech 3 - NOT FOUND! ============================================================ === DOOM 3 - id Tech 4 - AI.cpp @ 2105 ========================================================== rf: https://github.com/id-Software/DOOM-3/blob/master/neo/game/ai/AI.cpp /* ================ idAI::NewWanderDir ================ */ bool idAI::NewWanderDir( const idVec3 &dest ) { float deltax, deltay; float d[ 3 ]; float tdir, olddir, turnaround; move.nextWanderTime = gameLocal.time + ( gameLocal.random.RandomFloat() * 500 + 500 ); olddir = idMath::AngleNormalize360( ( int )( current_yaw / 45 ) * 45 ); turnaround = idMath::AngleNormalize360( olddir - 180 ); idVec3 org = physicsObj.GetOrigin(); deltax = dest.x - org.x; deltay = dest.y - org.y; if ( deltax > 10 ) { d[ 1 ]= 0; } else if ( deltax < -10 ) { d[ 1 ] = 180; } else { d[ 1 ] = DI_NODIR; } if ( deltay < -10 ) { d[ 2 ] = 270; } else if ( deltay > 10 ) { d[ 2 ] = 90; } else { d[ 2 ] = DI_NODIR; } // try direct route if ( d[ 1 ] != DI_NODIR && d[ 2 ] != DI_NODIR ) { if ( d[ 1 ] == 0 ) { tdir = d[ 2 ] == 90 ? 45 : 315; } else { tdir = d[ 2 ] == 90 ? 135 : 215; } if ( tdir != turnaround && StepDirection( tdir ) ) { return true; } } // try other directions if ( ( gameLocal.random.RandomInt() & 1 ) || abs( deltay ) > abs( deltax ) ) { tdir = d[ 1 ]; d[ 1 ] = d[ 2 ]; d[ 2 ] = tdir; } if ( d[ 1 ] != DI_NODIR && d[ 1 ] != turnaround && StepDirection( d[1] ) ) { return true; } if ( d[ 2 ] != DI_NODIR && d[ 2 ] != turnaround && StepDirection( d[ 2 ] ) ) { return true; } // there is no direct path to the player, so pick another direction if ( olddir != DI_NODIR && StepDirection( olddir ) ) { return true; } // randomly determine direction of search if ( gameLocal.random.RandomInt() & 1 ) { for( tdir = 0; tdir <= 315; tdir += 45 ) { if ( tdir != turnaround && StepDirection( tdir ) ) { return true; } } } else { for ( tdir = 315; tdir >= 0; tdir -= 45 ) { if ( tdir != turnaround && StepDirection( tdir ) ) { return true; } } } if ( turnaround != DI_NODIR && StepDirection( turnaround ) ) { return true; } // can't move StopMove( MOVE_STATUS_DEST_UNREACHABLE ); return false; }