void BuildSightDir(UINT32 dir, UINT32 *One, UINT32 *Two, UINT32 *Three, UINT32 *Four, UINT32 *Five) { switch(dir) { case NORTH : *One = NORTHWEST; *Two = NORTHEAST; *Three = NORTH; *Four = WEST; *Five = EAST; break; case NORTHEAST: *One = NORTH; *Two = EAST; *Three = NORTHEAST; *Four = NORTHWEST; *Five = SOUTHEAST; break; case EAST : *One = NORTHEAST; *Two = SOUTHEAST; *Three = EAST; *Four = NORTH; *Five = SOUTH; break; case SOUTHEAST: *One = EAST; *Two = SOUTH; *Three = SOUTHEAST; *Four = NORTHEAST; *Five = SOUTHWEST; break; case SOUTH : *One = SOUTHEAST; *Two = SOUTHWEST; *Three = SOUTH; *Four = EAST; *Five = WEST; break; case SOUTHWEST: *One = SOUTH; *Two = WEST; *Three = SOUTHWEST; *Four = SOUTHEAST; *Five = NORTHWEST; break; case WEST : *One = SOUTHWEST; *Two = NORTHWEST; *Three = WEST; *Four = SOUTH; *Five = NORTH; break; case NORTHWEST: *One = WEST; *Two = NORTH; *Three = NORTHWEST; *Four = SOUTHWEST; *Five = NORTHEAST; break; #ifdef BETAVERSION default: NumMessage("BuildSightDir: Invalid 'dir' value, = ",dir); #endif } }
INT8 RandomPointPatrolAI(SOLDIERTYPE *pSoldier) { INT16 sPatrolPoint; INT8 bOldOrders, bPatrolIndex; INT8 bCnt; sPatrolPoint = pSoldier->usPatrolGrid[pSoldier->bNextPatrolPnt]; // if we're already there, advance next patrol point if (pSoldier->sGridNo == sPatrolPoint || pSoldier->bNextPatrolPnt == 0) { // find next valid patrol point // we keep a count of the # of times we are in here to make sure we don't get into an endless //loop bCnt = 0; do { // usPatrolGrid[0] gets used for centre of close etc patrols, so we have to add 1 to the Random # bPatrolIndex = (INT8) PreRandom( pSoldier->bPatrolCnt ) + 1; sPatrolPoint = pSoldier->usPatrolGrid[ bPatrolIndex]; bCnt++; } while ( (sPatrolPoint == pSoldier->sGridNo) || ( (sPatrolPoint != NOWHERE) && (bCnt < pSoldier->bPatrolCnt) && (NewOKDestination(pSoldier,sPatrolPoint,IGNOREPEOPLE, pSoldier->bLevel ) < 1)) ); if (bCnt == pSoldier->bPatrolCnt) { // ok, we tried doing this randomly, didn't work well, so now do a linear search pSoldier->bNextPatrolPnt = 0; do { sPatrolPoint = NextPatrolPoint(pSoldier); } while ((sPatrolPoint != NOWHERE) && (NewOKDestination(pSoldier,sPatrolPoint,IGNOREPEOPLE, pSoldier->bLevel) < 1)); } // do nothing this time around if (pSoldier->sGridNo == sPatrolPoint) { return( FALSE ); } } // if we don't have a legal patrol point if (sPatrolPoint == NOWHERE) { #ifdef BETAVERSION NumMessage("PointPatrolAI: ERROR - no legal patrol point for %d",pSoldier->ubID); #endif // over-ride orders to something safer pSoldier->bOrders = FARPATROL; return(FALSE); } // make sure we can get there from here at this time, if we can't get all // the way there, at least do our best to get close if (LegalNPCDestination(pSoldier,sPatrolPoint,ENSURE_PATH,WATEROK,0)) { pSoldier->bPathStored = TRUE; // optimization - Ian pSoldier->usActionData = sPatrolPoint; } else { // temporarily extend roaming range to infinity by changing orders, else // this won't work if the next patrol point is > 10 tiles away! bOldOrders = pSoldier->bOrders; pSoldier->bOrders = SEEKENEMY; pSoldier->usActionData = GoAsFarAsPossibleTowards(pSoldier,sPatrolPoint,pSoldier->bAction); pSoldier->bOrders = bOldOrders; // if it's not possible to get any closer, that's OK, but fail this call if (pSoldier->usActionData == NOWHERE) return(FALSE); } // passed all tests - start moving towards next patrol point #ifdef DEBUGDECISIONS sprintf(tempstr,"%s - POINT PATROL to grid %d",pSoldier->name,pSoldier->usActionData); AIPopMessage(tempstr); #endif return(TRUE); }
int LegalNPCDestination(SOLDIERTYPE *pSoldier, INT16 sGridno, UINT8 ubPathMode, UINT8 ubWaterOK, UINT8 fFlags) { BOOLEAN fSkipTilesWithMercs; if ((sGridno < 0) || (sGridno >= GRIDSIZE)) { #ifdef RECORDNET fprintf(NetDebugFile,"LegalNPC->sDestination: ERROR - rcvd invalid gridno %d",gridno); #endif #ifdef BETAVERSION NumMessage("LegalNPC->sDestination: ERROR - rcvd invalid gridno ",gridno); #endif return(FALSE); } // return false if gridno on different level from merc if ( GridNoOnVisibleWorldTile( pSoldier->sGridNo ) && gpWorldLevelData[ pSoldier->sGridNo ].sHeight != gpWorldLevelData[ sGridno ].sHeight ) { return( FALSE ); } // skip mercs if turnbased and adjacent AND not doing an IGNORE_PATH check (which is used almost exclusively by GoAsFarAsPossibleTowards) fSkipTilesWithMercs = (gfTurnBasedAI && ubPathMode != IGNORE_PATH && SpacesAway( pSoldier->sGridNo, sGridno ) == 1 ); // if this gridno is an OK destination // AND the gridno is NOT in a tear-gassed tile when we have no gas mask // AND someone is NOT already standing there // AND we're NOT already standing at that gridno // AND the gridno hasn't been black-listed for us // Nov 28 98: skip people in destination tile if in turnbased if ( ( NewOKDestination(pSoldier, sGridno, fSkipTilesWithMercs, pSoldier->bLevel ) ) && ( !InGas( pSoldier, sGridno ) ) && ( sGridno != pSoldier->sGridNo ) && ( sGridno != pSoldier->sBlackList ) ) /* if ( ( NewOKDestination(pSoldier, sGridno, FALSE, pSoldier->bLevel ) ) && ( !(gpWorldLevelData[ sGridno ].ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS)) || ( pSoldier->inv[ HEAD1POS ].usItem == GASMASK || pSoldier->inv[ HEAD2POS ].usItem == GASMASK ) ) && ( sGridno != pSoldier->sGridNo ) && ( sGridno != pSoldier->sBlackList ) )*/ /* if ( ( NewOKDestination(pSoldier,sGridno,ALLPEOPLE, pSoldier->bLevel ) ) && ( !(gpWorldLevelData[ sGridno ].ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS)) || ( pSoldier->inv[ HEAD1POS ].usItem == GASMASK || pSoldier->inv[ HEAD2POS ].usItem == GASMASK ) ) && ( sGridno != pSoldier->sGridNo ) && ( sGridno != pSoldier->sBlackList ) ) */ { // if water's a problem, and gridno is in a water tile (bridges are OK) if (!ubWaterOK && Water(sGridno)) return(FALSE); // passed all checks, now try to make sure we can get there! switch (ubPathMode) { // if finding a path wasn't asked for (could have already been done, // for example), don't bother case IGNORE_PATH : return(TRUE); case ENSURE_PATH : if ( FindBestPath( pSoldier, sGridno, pSoldier->bLevel, WALKING, COPYROUTE, fFlags ) ) { return(TRUE); // legal destination } else // got this far, but found no clear path, { // so test fails return(FALSE); } // *** NOTE: movement mode hardcoded to WALKING !!!!! case ENSURE_PATH_COST: return(PlotPath(pSoldier,sGridno,FALSE,FALSE,FALSE,WALKING,FALSE,FALSE,0)); default : #ifdef BETAVERSION NumMessage("LegalNPC->sDestination: ERROR - illegal pathMode = ",ubPathMode); #endif return(FALSE); } } else // something failed - didn't even have to test path return(FALSE); // illegal destination }
INT8 PointPatrolAI(SOLDIERTYPE *pSoldier) { INT16 sPatrolPoint; INT8 bOldOrders; sPatrolPoint = pSoldier->usPatrolGrid[pSoldier->bNextPatrolPnt]; // if we're already there, advance next patrol point if (pSoldier->sGridNo == sPatrolPoint || pSoldier->bNextPatrolPnt == 0) { // find next valid patrol point do { sPatrolPoint = NextPatrolPoint(pSoldier); } while ((sPatrolPoint != NOWHERE) && (NewOKDestination(pSoldier,sPatrolPoint,IGNOREPEOPLE, pSoldier->bLevel) < 1)); // if we're back where we started, then ALL other patrol points are junk! if (pSoldier->sGridNo == sPatrolPoint) { #ifdef BETAVERSION NumMessage("PROBLEM WITH SCENARIO: All other patrol points are invalid for guynum ",pSoldier->ubID); #endif // force change of orders & an abort sPatrolPoint = NOWHERE; } } // if we don't have a legal patrol point if (sPatrolPoint == NOWHERE) { #ifdef BETAVERSION NumMessage("PointPatrolAI: ERROR - no legal patrol point for %d",pSoldier->ubID); #endif // over-ride orders to something safer pSoldier->bOrders = FARPATROL; return(FALSE); } // make sure we can get there from here at this time, if we can't get all // the way there, at least do our best to get close if (LegalNPCDestination(pSoldier,sPatrolPoint,ENSURE_PATH,WATEROK,0)) { pSoldier->bPathStored = TRUE; // optimization - Ian pSoldier->usActionData = sPatrolPoint; } else { // temporarily extend roaming range to infinity by changing orders, else // this won't work if the next patrol point is > 10 tiles away! bOldOrders = pSoldier->bOrders; pSoldier->bOrders = ONCALL; pSoldier->usActionData = GoAsFarAsPossibleTowards(pSoldier,sPatrolPoint,pSoldier->bAction); pSoldier->bOrders = bOldOrders; // if it's not possible to get any closer, that's OK, but fail this call if (pSoldier->usActionData == NOWHERE) return(FALSE); } // passed all tests - start moving towards next patrol point #ifdef DEBUGDECISIONS sprintf(tempstr,"%s - POINT PATROL to grid %d",pSoldier->name,pSoldier->usActionData); AIPopMessage(tempstr); #endif return(TRUE); }
void MakeClosestEnemyChosenOne() { UINT32 cnt; INT16 sPathCost, sShortestPath = 1000; INT8 bOldKeys = -1; UINT8 ubClosestEnemy = NOBODY; SOLDIERTYPE * pSoldier; INT8 bPanicTrigger; INT16 sPanicTriggerGridNo; if ( ! (gTacticalStatus.fPanicFlags & PANIC_TRIGGERS_HERE) ) { #ifdef BETAVERSION PopMessage("MakeClosestEnemyChosenOne: ERROR - Panic Trigger is NOWHERE"); #endif return; } if (!NeedToRadioAboutPanicTrigger() ) { // no active panic triggers return; } // consider every enemy, looking for the closest capable, unbusy one for (cnt = 0; cnt < guiNumMercSlots; cnt++) { pSoldier = MercSlots[cnt]; if (!pSoldier) // if this merc is inactive, or not here { continue; } // if this merc is unconscious, or dead if (pSoldier->bLife < OKLIFE) { continue; // next soldier } // if this guy's too tired to go if (pSoldier->bBreath < OKBREATH) { continue; // next soldier } if ( gWorldSectorX == TIXA_SECTOR_X && gWorldSectorY == TIXA_SECTOR_Y ) { if ( pSoldier->ubProfile != WARDEN ) { continue; } } else { // only consider for army guys if (pSoldier->bTeam != ENEMY_TEAM ) { continue; } } // if this guy is in battle with opponent(s) if (pSoldier->bOppCnt > 0) { continue; // next soldier } // if this guy is still in serious shock if (pSoldier->bShock > 2) { continue; // next soldier } if ( pSoldier->bLevel != 0 ) { // screw having guys on the roof go for panic triggers! continue; // next soldier } bPanicTrigger = ClosestPanicTrigger( pSoldier ); if (bPanicTrigger == -1) { continue; // next soldier } sPanicTriggerGridNo = gTacticalStatus.sPanicTriggerGridNo[ bPanicTrigger ]; if (sPanicTriggerGridNo == NOWHERE) { // this should never happen! continue; } // remember whether this guy had keys before //bOldKeys = pSoldier->bHasKeys; // give him keys to see if with them he can get to the panic trigger pSoldier->bHasKeys = (pSoldier->bHasKeys << 1) | 1; // we now path directly to the panic trigger // if he can't get to a spot where he could get at the panic trigger /* if ( FindAdjacentGridEx( pSoldier, gTacticalStatus.sPanicTriggerGridno, &ubDirection, &sAdjSpot, FALSE, FALSE ) == -1 ) { pSoldier->bHasKeys = bOldKeys; continue; // next merc } */ // ok, this enemy appears to be eligible // FindAdjacentGrid set HandGrid for us. If we aren't at that spot already if (pSoldier->sGridNo != sPanicTriggerGridNo) { // get the AP cost for this enemy to go to target position sPathCost = PlotPath( pSoldier, sPanicTriggerGridNo, FALSE, FALSE, FALSE, WALKING, FALSE, FALSE, 0); } else { sPathCost = 0; } // set his keys value back to what it was before this hack pSoldier->bHasKeys = (pSoldier->bHasKeys >> 1 ); // if he can get there (or is already there!) if (sPathCost || (pSoldier->sGridNo == sPanicTriggerGridNo)) { if (sPathCost < sShortestPath) { sShortestPath = sPathCost; ubClosestEnemy = pSoldier->ubID; } } //else //NameMessage(pSoldier,"can't get there..."); } // if we found have an eligible enemy, make him our "chosen one" if (ubClosestEnemy < NOBODY) { gTacticalStatus.ubTheChosenOne = ubClosestEnemy; // flag him as the chosen one #ifdef TESTVERSION NumMessage("TEST MSG: The chosen one is ",TheChosenOne); #endif pSoldier = MercPtrs[gTacticalStatus.ubTheChosenOne]; if ( pSoldier->bAlertStatus < STATUS_RED ) { pSoldier->bAlertStatus = STATUS_RED; CheckForChangingOrders( pSoldier ); } SetNewSituation( pSoldier ); // set new situation for the chosen one pSoldier->bHasKeys = (pSoldier->bHasKeys << 1) | 1; // cheat and give him keys to every door //pSoldier->bHasKeys = TRUE; } #ifdef TESTVERSION else PopMessage("TEST MSG: Couldn't find anyone eligible to become TheChosenOne!"); #endif }