1 line
41 KiB
C
Executable File
1 line
41 KiB
C
Executable File
//============================================================
|
|
//============================================================
|
|
//== ==
|
|
//== Computer Persona Handling Routines ==
|
|
//== ==
|
|
//============================================================
|
|
//============================================================
|
|
|
|
|
|
//======================================================== Includes
|
|
|
|
#include "Globals.h"
|
|
#include "UnivUtilities.h"
|
|
#include "Computer.h"
|
|
#include "Dynamics.h"
|
|
#include "SoundUtils.h"
|
|
|
|
|
|
//======================================================== Functions
|
|
//======================================================== DiagonalToPlayer
|
|
|
|
short DiagonalToPerson (playerType *who)
|
|
|
|
{
|
|
short newDirection;
|
|
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
if (thePlayer.xPos > theOpponent.xPos)
|
|
{
|
|
if (thePlayer.zPos > theOpponent.zPos)
|
|
newDirection = kFacingNorthEast;
|
|
else
|
|
newDirection = kFacingSouthEast;
|
|
}
|
|
else
|
|
{
|
|
if (thePlayer.zPos > theOpponent.zPos)
|
|
newDirection = kFacingNorthWest;
|
|
else
|
|
newDirection = kFacingSouthWest;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (theOpponent.xPos > thePlayer.xPos)
|
|
{
|
|
if (theOpponent.zPos > thePlayer.zPos)
|
|
newDirection = kFacingNorthEast;
|
|
else
|
|
newDirection = kFacingSouthEast;
|
|
}
|
|
else
|
|
{
|
|
if (theOpponent.zPos > thePlayer.zPos)
|
|
newDirection = kFacingNorthWest;
|
|
else
|
|
newDirection = kFacingSouthWest;
|
|
}
|
|
}
|
|
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== DiagonalToBall
|
|
|
|
short DiagonalToBall (playerType *who)
|
|
|
|
{
|
|
short newDirection;
|
|
|
|
if (theBall.xPos > who->xPos)
|
|
{
|
|
if (theBall.zPos > who->zPos)
|
|
newDirection = kFacingNorthEast;
|
|
else
|
|
newDirection = kFacingSouthEast;
|
|
}
|
|
else
|
|
{
|
|
if (theBall.zPos > who->zPos)
|
|
newDirection = kFacingNorthWest;
|
|
else
|
|
newDirection = kFacingSouthWest;
|
|
}
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== OctalToPoint
|
|
|
|
short OctalToPoint (playerType *who, register short xPos, register short zPos)
|
|
|
|
{
|
|
register long rise, run;
|
|
short newDirection;
|
|
|
|
if (xPos > who->xPos)
|
|
{
|
|
if (zPos > who->zPos)
|
|
newDirection = kFacingNorthEast;
|
|
else
|
|
newDirection = kFacingSouthEast;
|
|
}
|
|
else
|
|
{
|
|
if (zPos > who->zPos)
|
|
newDirection = kFacingNorthWest;
|
|
else
|
|
newDirection = kFacingSouthWest;
|
|
}
|
|
|
|
switch (newDirection)
|
|
{
|
|
case kFacingNorthEast:
|
|
rise = (long)zPos - (long)who->zPos;
|
|
run = (long)xPos - (long)who->xPos;
|
|
if ((rise * 2) < run)
|
|
{
|
|
newDirection = kFacingEast;
|
|
}
|
|
else if (rise > (run * 2))
|
|
{
|
|
newDirection = kFacingNorth;
|
|
}
|
|
else
|
|
{
|
|
newDirection = kFacingNorthEast;
|
|
}
|
|
break;
|
|
case kFacingNorthWest:
|
|
rise = (long)zPos - (long)who->zPos;
|
|
run = (long)who->xPos - (long)xPos;
|
|
if ((rise * 2) < run)
|
|
{
|
|
newDirection = kFacingWest;
|
|
}
|
|
else if (rise > (run * 2))
|
|
{
|
|
newDirection = kFacingNorth;
|
|
}
|
|
else
|
|
{
|
|
newDirection = kFacingNorthWest;
|
|
}
|
|
break;
|
|
case kFacingSouthEast:
|
|
rise = (long)who->zPos - (long)zPos;
|
|
run = (long)xPos - (long)who->xPos;
|
|
if ((rise * 2) < run)
|
|
{
|
|
newDirection = kFacingEast;
|
|
}
|
|
else if (rise > (run * 2))
|
|
{
|
|
newDirection = kFacingSouth;
|
|
}
|
|
else
|
|
{
|
|
newDirection = kFacingSouthEast;
|
|
}
|
|
break;
|
|
case kFacingSouthWest:
|
|
rise = (long)who->zPos - (long)zPos;
|
|
run = (long)who->xPos - (long)xPos;
|
|
if ((rise * 2) < run)
|
|
{
|
|
newDirection = kFacingWest;
|
|
}
|
|
else if (rise > (run * 2))
|
|
{
|
|
newDirection = kFacingSouth;
|
|
}
|
|
else
|
|
{
|
|
newDirection = kFacingSouthWest;
|
|
}
|
|
break;
|
|
}
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== LookUpBoardForce
|
|
|
|
void LookUpBoardForce (playerType *who)
|
|
|
|
{
|
|
short boardXForce, boardZForce;
|
|
|
|
if ((who->justHitWall == 0) && (who->justHitOpponent == 0))
|
|
{
|
|
boardXForce = boardForceTable[who->direction][kXComponent];
|
|
boardZForce = boardForceTable[who->direction][kZComponent];
|
|
|
|
if (who->bashApplied)
|
|
{
|
|
boardXForce *= 4; // 200% inc in board force
|
|
boardZForce *= 4;
|
|
}
|
|
|
|
if (who->posture == kCrouching)
|
|
{
|
|
boardXForce += boardXForce / kAddForceFract; // 25% inc in board force
|
|
boardZForce += boardZForce / kAddForceFract; // tried 50%, but harsh
|
|
}
|
|
|
|
who->xVel += boardXForce;
|
|
who->zVel += boardZForce;
|
|
}
|
|
}
|
|
|
|
|
|
//======================================================== NearTheBall
|
|
|
|
Boolean NearTheBall (playerType *who)
|
|
|
|
{
|
|
#define kNearDistSquared 16777216L // a distance of 64
|
|
register long xDistance, zDistance, distanceSquared;
|
|
Boolean nearBall;
|
|
|
|
xDistance = who->xPos - theBall.xPos;
|
|
zDistance = who->zPos - theBall.zPos;
|
|
distanceSquared = (xDistance * xDistance) + (zDistance * zDistance);
|
|
|
|
if (distanceSquared < kNearDistSquared)
|
|
nearBall = TRUE;
|
|
else
|
|
nearBall = FALSE;
|
|
|
|
return (nearBall);
|
|
}
|
|
|
|
|
|
//======================================================== NearTheEdge
|
|
|
|
Boolean NearTheEdge (playerType *who)
|
|
|
|
{
|
|
#define kSmEdgeDistSquared 108826624L // a distance of 163
|
|
#define kLgEdgeDistSquared 170459136L // a distance of 204
|
|
register long distanceSquared;
|
|
Boolean nearEdge;
|
|
|
|
distanceSquared = ((long)who->xPos * (long)who->xPos) +
|
|
((long)who->zPos * (long)who->zPos);
|
|
if (arenaSize == kLargeArena)
|
|
{
|
|
if (distanceSquared > kLgEdgeDistSquared)
|
|
nearEdge = TRUE;
|
|
else
|
|
nearEdge = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (distanceSquared > kLgEdgeDistSquared)
|
|
nearEdge = TRUE;
|
|
else
|
|
nearEdge = FALSE;
|
|
}
|
|
|
|
return(nearEdge);
|
|
}
|
|
|
|
|
|
//======================================================== NearTheEdgeSmarter
|
|
|
|
Boolean NearTheEdgeSmarter (playerType *who)
|
|
|
|
{
|
|
#define kFramesConsidered 8L
|
|
#define kSmEdgeDistSquared 108826624L // a distance of 163
|
|
#define kLgEdgeDistSquared 170459136L // a distance of 204
|
|
register long distanceSquared;
|
|
long anticipatedX, anticipatedZ;
|
|
Boolean nearEdge;
|
|
|
|
anticipatedX = (long)who->xPos + ((long)(who->xVel /
|
|
kVelocitySensitive) * kFramesConsidered);
|
|
anticipatedZ = (long)who->zPos + ((long)(who->zVel /
|
|
kVelocitySensitive) * kFramesConsidered);
|
|
distanceSquared = (anticipatedX * anticipatedX) + (anticipatedZ * anticipatedZ);
|
|
|
|
if (arenaSize == kLargeArena)
|
|
{
|
|
if (distanceSquared > kLgEdgeDistSquared)
|
|
nearEdge = TRUE;
|
|
else
|
|
nearEdge = FALSE;
|
|
|
|
}
|
|
else
|
|
{
|
|
if (distanceSquared > kSmEdgeDistSquared)
|
|
nearEdge = TRUE;
|
|
else
|
|
nearEdge = FALSE;
|
|
}
|
|
|
|
return(nearEdge);
|
|
}
|
|
|
|
|
|
//======================================================== NearTheGoal
|
|
|
|
Boolean NearTheGoal (playerType *who)
|
|
|
|
{
|
|
#define kSmGoalXThreshRt 9123 // 84% of distance (10861)
|
|
#define kSmGoalXThreshLf -9123 // 84% of distance from center
|
|
#define kSmGoalZThresh 9123 // 84% of distance from center
|
|
#define kLgGoalXThreshRt 11811 // 87% of distance from center
|
|
#define kLgGoalXThreshLf -11811 // 87% of distance from center
|
|
#define kLgGoalZThresh 11811 // 87% of distance from center
|
|
Boolean nearGoal;
|
|
|
|
if (arenaSize == kLargeArena)
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
{
|
|
if ((who->xPos > kLgGoalXThreshRt) && (who->zPos > kLgGoalZThresh))
|
|
nearGoal = TRUE;
|
|
else
|
|
nearGoal = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if ((who->xPos < kLgGoalXThreshLf) && (who->zPos > kLgGoalZThresh))
|
|
nearGoal = TRUE;
|
|
else
|
|
nearGoal = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
{
|
|
if ((who->xPos > kSmGoalXThreshRt) && (who->zPos > kSmGoalZThresh))
|
|
nearGoal = TRUE;
|
|
else
|
|
nearGoal = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if ((who->xPos < kSmGoalXThreshLf) && (who->zPos > kSmGoalZThresh))
|
|
nearGoal = TRUE;
|
|
else
|
|
nearGoal = FALSE;
|
|
}
|
|
}
|
|
|
|
return (nearGoal);
|
|
}
|
|
|
|
|
|
//======================================================== NearPerson
|
|
|
|
Boolean NearPerson (void)
|
|
|
|
{
|
|
#define kNearPlayerDistSqr 58982400L // a distance of 120
|
|
register long xDistance, zDistance, distanceSquared;
|
|
Boolean nearPlayer;
|
|
|
|
xDistance = theOpponent.xPos - thePlayer.xPos;
|
|
zDistance = theOpponent.zPos - thePlayer.zPos;
|
|
distanceSquared = (xDistance * xDistance) + (zDistance * zDistance);
|
|
|
|
if (distanceSquared < kNearPlayerDistSqr)
|
|
nearPlayer = TRUE;
|
|
else
|
|
nearPlayer = FALSE;
|
|
|
|
return (nearPlayer);
|
|
}
|
|
|
|
|
|
//======================================================== DecentShot
|
|
|
|
Boolean DecentShot (playerType *who)
|
|
|
|
{
|
|
#define kFramesToTrackBall 8
|
|
register long newVelX, newVelZ;
|
|
register long newPosX, newPosZ;
|
|
short i, ballsPlace, indexX, indexZ;
|
|
Boolean shootIt;
|
|
|
|
newVelX = (long)who->xVel / kVelocitySensitive;
|
|
newVelZ = (long)who->zVel / kVelocitySensitive;
|
|
|
|
newPosX = (long)who->xPos;
|
|
newPosZ = (long)who->zPos;
|
|
|
|
shootIt = FALSE;
|
|
|
|
for (i = 0; i < kFramesToTrackBall; i++)
|
|
{
|
|
newPosX += newVelX;
|
|
newPosZ += newVelZ;
|
|
|
|
indexX = abs(newPosX / 512);
|
|
indexZ = abs(newPosZ / 512);
|
|
|
|
ballsPlace = *(littleForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
|
|
|
if (((ballsPlace == kBackBoard) || (ballsPlace == kGoalPath)) &&
|
|
(newPosZ > 0) && (((who->whichGoal == kRightGoal) &&
|
|
(newPosX > 0)) || ((who->whichGoal == kLeftGoal) && (newPosX < 0))))
|
|
{
|
|
shootIt = TRUE;
|
|
break;
|
|
}
|
|
else if (ballsPlace == kOutOBounds)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (shootIt);
|
|
}
|
|
|
|
|
|
//======================================================== ExcellentShot
|
|
|
|
Boolean ExcellentShot (playerType *who)
|
|
|
|
{
|
|
#define kFramesToTrackBall 8
|
|
register long newVelX, newVelZ;
|
|
register long newPosX, newPosZ;
|
|
short i, ballsPlace, indexX, indexZ;
|
|
Boolean shootIt;
|
|
|
|
newVelX = (long)who->xVel / kVelocitySensitive;
|
|
newVelZ = (long)who->zVel / kVelocitySensitive;
|
|
|
|
newPosX = (long)who->xPos;
|
|
newPosZ = (long)who->zPos;
|
|
|
|
shootIt = FALSE;
|
|
|
|
for (i = 0; i < kFramesToTrackBall; i++)
|
|
{
|
|
newPosX += newVelX;
|
|
newPosZ += newVelZ;
|
|
|
|
indexX = abs(newPosX / 512);
|
|
indexZ = abs(newPosZ / 512);
|
|
|
|
ballsPlace = *(proForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
|
|
|
if ((ballsPlace == kGoalPath) && (newPosZ > 0) &&
|
|
(((who->whichGoal == kRightGoal) && (newPosX > 0)) ||
|
|
((who->whichGoal == kLeftGoal) && (newPosX < 0))))
|
|
{
|
|
shootIt = TRUE;
|
|
break;
|
|
}
|
|
else if (ballsPlace == kOutOBounds)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (shootIt);
|
|
}
|
|
|
|
|
|
//======================================================== ExcellentShot
|
|
|
|
Boolean ExcellentDirectionalShot (playerType *who, short directed)
|
|
|
|
{
|
|
#define kFramesTrackDirBall 8
|
|
register short newPosX, newPosZ;
|
|
short newVelX, newVelZ;
|
|
short i, ballsPlace, indexX, indexZ;
|
|
Boolean shootIt;
|
|
|
|
newVelX = boardForceTable[directed][kXComponent] * kPersonImpulse;
|
|
newVelZ = boardForceTable[directed][kZComponent] * kPersonImpulse;
|
|
|
|
newPosX = who->xPos + newVelX;
|
|
newPosZ = who->zPos + newVelZ;
|
|
|
|
newVelX += who->xVel / kVelocitySensitive;
|
|
newVelZ += who->zVel / kVelocitySensitive;
|
|
|
|
shootIt = FALSE;
|
|
|
|
for (i = 0; i < kFramesTrackDirBall; i++)
|
|
{
|
|
newPosX += newVelX;
|
|
newPosZ += newVelZ;
|
|
|
|
indexX = abs(newPosX / 512);
|
|
indexZ = abs(newPosZ / 512);
|
|
|
|
ballsPlace = *(littleForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
|
|
|
if (who->whichGoal == kRightGoal)
|
|
{
|
|
if ((ballsPlace == kGoalPath) && (newPosZ > 0) && (newPosX > 0))
|
|
{
|
|
shootIt = TRUE;
|
|
break;
|
|
}
|
|
else if ((ballsPlace == kOutOBounds) || (ballsPlace == kBackBoard))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((ballsPlace == kGoalPath) && (newPosZ > 0) && (newPosX < 0))
|
|
{
|
|
shootIt = TRUE;
|
|
break;
|
|
}
|
|
else if ((ballsPlace == kOutOBounds) || (ballsPlace == kBackBoard))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (shootIt);
|
|
}
|
|
|
|
|
|
//======================================================== PointingToDisaster
|
|
|
|
Boolean PointingToDisaster (playerType *who)
|
|
|
|
{
|
|
#define kFarDisasterLookAhead 128L // was 144L
|
|
#define kSmDisasterSquared 235929600L // a distance of 240
|
|
#define kLgDisasterSquared 368640000L // a distance of 300
|
|
long possibleX, possibleZ, distanceSquared;
|
|
Boolean nearDisaster;
|
|
|
|
possibleX = (long)who->xPos + (long)boardForceTable[who->direction][kXComponent] *
|
|
kFarDisasterLookAhead;
|
|
possibleZ = (long)who->zPos + (long)boardForceTable[who->direction][kZComponent] *
|
|
kFarDisasterLookAhead;
|
|
|
|
distanceSquared = (possibleX * possibleX) + (possibleZ * possibleZ);
|
|
|
|
if (arenaSize == kLargeArena)
|
|
{
|
|
if (distanceSquared > kLgDisasterSquared)
|
|
{
|
|
nearDisaster = TRUE;
|
|
}
|
|
else
|
|
{
|
|
nearDisaster = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (distanceSquared > kSmDisasterSquared)
|
|
{
|
|
nearDisaster = TRUE;
|
|
}
|
|
else
|
|
{
|
|
nearDisaster = FALSE;
|
|
}
|
|
}
|
|
|
|
return(nearDisaster);
|
|
}
|
|
|
|
|
|
//======================================================== RunTheDiagonalNE
|
|
|
|
short RunTheDiagonalNE (playerType *who)
|
|
|
|
{
|
|
short newDirection;
|
|
|
|
switch (who->direction)
|
|
{
|
|
case kFacingNorthEast:
|
|
if ((who->xVel < 0) && (who->zVel < 0))
|
|
{
|
|
if ((who->xPos < 0) && (who->zPos < 0))
|
|
newDirection = kFacingNorthEast;
|
|
else
|
|
newDirection = kFacingSouthWest;
|
|
}
|
|
else
|
|
{
|
|
newDirection = kFacingNorthEast;
|
|
if (NearTheEdge(who) && (who->xPos > 0) && (who->zPos > 0))
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
break;
|
|
case kFacingSouthWest:
|
|
if ((who->xVel > 0) && (who->zVel > 0))
|
|
{
|
|
if ((who->xPos > 0) && (who->zPos > 0))
|
|
newDirection = kFacingSouthWest;
|
|
else
|
|
newDirection = kFacingNorthEast;
|
|
}
|
|
else
|
|
{
|
|
if (NearTheEdge(who) && (who->xPos < 0) && (who->zPos < 0))
|
|
newDirection = kFacingNorthEast;
|
|
else
|
|
newDirection = kFacingSouthWest;
|
|
}
|
|
break;
|
|
default:
|
|
newDirection = kFacingSouthWest;
|
|
break;
|
|
}
|
|
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== RunTheDiagonalNW
|
|
|
|
short RunTheDiagonalNW (playerType *who)
|
|
|
|
{
|
|
short newDirection;
|
|
|
|
switch (who->direction)
|
|
{
|
|
case kFacingNorthWest:
|
|
if ((who->xVel > 0) && (who->zVel < 0))
|
|
{
|
|
if ((who->xPos > 0) && (who->zPos < 0))
|
|
newDirection = kFacingNorthWest;
|
|
else
|
|
newDirection = kFacingSouthEast;
|
|
}
|
|
else
|
|
{
|
|
newDirection = kFacingNorthWest;
|
|
if (NearTheEdge(who) && (who->xPos < 0) && (who->zPos > 0))
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
break;
|
|
case kFacingSouthEast:
|
|
if ((who->xVel > 0) && (who->zVel > 0))
|
|
{
|
|
if ((who->xPos < 0) && (who->zPos > 0))
|
|
newDirection = kFacingSouthEast;
|
|
else
|
|
newDirection = kFacingNorthWest;
|
|
}
|
|
else
|
|
{
|
|
if (NearTheEdge(who) && (who->xPos > 0) && (who->zPos < 0))
|
|
newDirection = kFacingNorthWest;
|
|
else
|
|
newDirection = kFacingSouthEast;
|
|
}
|
|
break;
|
|
default:
|
|
newDirection = kFacingSouthEast;
|
|
break;
|
|
}
|
|
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== RunTheDiagonalSmarterNE
|
|
|
|
short RunTheDiagonalSmarterNE (playerType *who)
|
|
|
|
{
|
|
short newDirection;
|
|
|
|
switch (who->direction)
|
|
{
|
|
case kFacingNorthEast:
|
|
if ((who->xVel < 0) && (who->zVel < 0))
|
|
{
|
|
if ((who->xPos < 0) && (who->zPos < 0))
|
|
newDirection = kFacingNorthEast;
|
|
else
|
|
newDirection = kFacingSouthWest;
|
|
}
|
|
else
|
|
{
|
|
newDirection = kFacingNorthEast;
|
|
if (NearTheEdgeSmarter(who) && (who->xPos > 0) && (who->zPos > 0) &&
|
|
(DecentShot(who)))
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
break;
|
|
case kFacingSouthWest:
|
|
if ((who->xVel > 0) && (who->zVel > 0))
|
|
{
|
|
if ((who->xPos > 0) && (who->zPos > 0))
|
|
newDirection = kFacingSouthWest;
|
|
else
|
|
newDirection = kFacingNorthEast;
|
|
}
|
|
else
|
|
{
|
|
if (NearTheEdgeSmarter(who) && (who->xPos < 0) && (who->zPos < 0))
|
|
newDirection = kFacingNorthEast;
|
|
else
|
|
newDirection = kFacingSouthWest;
|
|
}
|
|
break;
|
|
default:
|
|
newDirection = kFacingSouthWest;
|
|
break;
|
|
}
|
|
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== RunTheDiagonalSmarterNW
|
|
|
|
short RunTheDiagonalSmarterNW (playerType *who)
|
|
|
|
{
|
|
short newDirection;
|
|
|
|
switch (who->direction)
|
|
{
|
|
case kFacingNorthWest:
|
|
if ((who->xVel > 0) && (who->zVel < 0)) // bugs in this code!
|
|
{
|
|
if ((who->xPos > 0) && (who->zPos < 0))
|
|
newDirection = kFacingNorthWest;
|
|
else
|
|
newDirection = kFacingSouthEast;
|
|
}
|
|
else
|
|
{
|
|
newDirection = kFacingNorthWest;
|
|
if (NearTheEdgeSmarter(who) && (who->xPos < 0) && (who->zPos > 0) &&
|
|
DecentShot(who))
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
break;
|
|
case kFacingSouthEast:
|
|
if ((who->xVel < 0) && (who->zVel > 0))
|
|
{
|
|
if ((who->xPos < 0) && (who->zPos > 0))
|
|
newDirection = kFacingSouthEast;
|
|
else
|
|
newDirection = kFacingNorthWest;
|
|
}
|
|
else
|
|
{
|
|
if (NearTheEdgeSmarter(who) && (who->xPos > 0) && (who->zPos < 0))
|
|
newDirection = kFacingNorthWest;
|
|
else
|
|
newDirection = kFacingSouthEast;
|
|
}
|
|
break;
|
|
default:
|
|
newDirection = kFacingSouthEast;
|
|
break;
|
|
}
|
|
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== RunTheDiagonalSmartestNE
|
|
|
|
short RunTheDiagonalSmartestNE (playerType *who)
|
|
|
|
{
|
|
short newDirection;
|
|
|
|
switch (who->direction)
|
|
{
|
|
case kFacingNorthEast:
|
|
if ((who->xVel < 0) && (who->zVel < 0))
|
|
{
|
|
if ((who->xPos < 0) && (who->zPos < 0))
|
|
newDirection = kFacingNorthEast;
|
|
else
|
|
newDirection = kFacingSouthWest;
|
|
}
|
|
else
|
|
{
|
|
newDirection = kFacingNorthEast;
|
|
if (NearTheEdgeSmarter(who) && (who->xPos > 0) && (who->zPos > 0) &&
|
|
ExcellentShot(who))
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
break;
|
|
case kFacingSouthWest:
|
|
if ((who->xVel > 0) && (who->zVel > 0))
|
|
{
|
|
if ((who->xPos > 0) && (who->zPos > 0))
|
|
newDirection = kFacingSouthWest;
|
|
else
|
|
newDirection = kFacingNorthEast;
|
|
}
|
|
else
|
|
{
|
|
if (NearTheEdgeSmarter(who) && (who->xPos < 0) && (who->zPos < 0))
|
|
newDirection = kFacingNorthEast;
|
|
else
|
|
newDirection = kFacingSouthWest;
|
|
}
|
|
break;
|
|
default:
|
|
newDirection = kFacingSouthWest;
|
|
break;
|
|
}
|
|
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== RunTheDiagonalSmartestNW
|
|
|
|
short RunTheDiagonalSmartestNW (playerType *who)
|
|
|
|
{
|
|
short newDirection;
|
|
|
|
switch (who->direction)
|
|
{
|
|
case kFacingNorthWest:
|
|
if ((who->xVel > 0) && (who->zVel < 0))
|
|
{
|
|
if ((who->xPos > 0) && (who->zPos < 0)) // bugs in this function
|
|
newDirection = kFacingNorthWest;
|
|
else
|
|
newDirection = kFacingSouthEast;
|
|
}
|
|
else
|
|
{
|
|
newDirection = kFacingNorthWest;
|
|
if (NearTheEdgeSmarter(who) && (who->xPos < 0) && (who->zPos > 0) &&
|
|
ExcellentShot(who))
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
break;
|
|
case kFacingSouthEast:
|
|
if ((who->xVel < 0) && (who->zVel > 0))
|
|
{
|
|
if ((who->xPos < 0) && (who->zPos > 0))
|
|
newDirection = kFacingSouthEast;
|
|
else
|
|
newDirection = kFacingNorthWest;
|
|
}
|
|
else
|
|
{
|
|
if (NearTheEdgeSmarter(who) && (who->xPos > 0) && (who->zPos < 0))
|
|
newDirection = kFacingNorthWest;
|
|
else
|
|
newDirection = kFacingSouthEast;
|
|
}
|
|
break;
|
|
default:
|
|
newDirection = kFacingSouthEast;
|
|
break;
|
|
}
|
|
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== SeekPlayerGoal
|
|
|
|
short SeekPersonsGoal (playerType *who)
|
|
|
|
{
|
|
#define kSmallArenaGoalXSRt -10861
|
|
#define kSmallArenaGoalXSLf 10861
|
|
#define kSmallArenaGoalZS 10861
|
|
#define kLargeArenaGoalXSRt -13576
|
|
#define kLargeArenaGoalXSLf 13576
|
|
#define kLargeArenaGoalZS 13576
|
|
short newDirection;
|
|
|
|
if (who->whichGoal == kRightGoal)
|
|
{
|
|
if (arenaSize == kLargeArena)
|
|
newDirection = OctalToPoint(who, kLargeArenaGoalXSRt, kLargeArenaGoalZS);
|
|
else
|
|
newDirection = OctalToPoint(who, kSmallArenaGoalXSRt, kSmallArenaGoalZS);
|
|
}
|
|
else
|
|
{
|
|
if (arenaSize == kLargeArena)
|
|
newDirection = OctalToPoint(who, kLargeArenaGoalXSLf, kLargeArenaGoalZS);
|
|
else
|
|
newDirection = OctalToPoint(who, kSmallArenaGoalXSLf, kSmallArenaGoalZS);
|
|
}
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== AnticipateBall
|
|
|
|
short AnticipateBall (playerType *who, short framesAhead)
|
|
|
|
{
|
|
register long newX, newZ;
|
|
short newDirection;
|
|
|
|
if (NearTheBall(who))
|
|
{
|
|
newDirection = OctalToPoint(who, theBall.xPos, theBall.zPos);
|
|
}
|
|
else
|
|
{
|
|
newX = (long)theBall.xPos + (long)theBall.xVel / kVelocitySensitive *
|
|
(long)framesAhead;
|
|
newZ = (long)theBall.zPos + (long)theBall.zVel / kVelocitySensitive *
|
|
(long)framesAhead;
|
|
|
|
if (newX > kMaxShort)
|
|
newX = kMaxShort;
|
|
if (newX < kMinShort)
|
|
newX = kMinShort;
|
|
if (newZ > kMaxShort)
|
|
newZ = kMaxShort;
|
|
if (newZ < kMinShort)
|
|
newZ = kMinShort;
|
|
|
|
newDirection = OctalToPoint(who, (short)newX, (short)newZ);
|
|
}
|
|
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== AnticipatePersonsFlank
|
|
|
|
short AnticipatePersonsFlank (playerType *who, short framesAhead)
|
|
|
|
{
|
|
#define kFlankingDistXRt -3072 // -48 pixels
|
|
#define kFlankingDistXLf 3072 // -48 pixels
|
|
#define kFlankingDistZ 3072 // 48 pixels
|
|
register long newX, newZ;
|
|
short newDirection;
|
|
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
{
|
|
newX = (long)thePlayer.xPos + kFlankingDistXRt + (long)thePlayer.xVel /
|
|
kVelocitySensitive * (long)framesAhead;
|
|
}
|
|
else
|
|
{
|
|
newX = (long)thePlayer.xPos + kFlankingDistXLf + (long)thePlayer.xVel /
|
|
kVelocitySensitive * (long)framesAhead;
|
|
}
|
|
newZ = (long)thePlayer.zPos + kFlankingDistZ + (long)thePlayer.zVel /
|
|
kVelocitySensitive * (long)framesAhead;
|
|
}
|
|
else
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
{
|
|
newX = (long)theOpponent.xPos + kFlankingDistXRt + (long)theOpponent.xVel /
|
|
kVelocitySensitive * (long)framesAhead;
|
|
}
|
|
else
|
|
{
|
|
newX = (long)theOpponent.xPos + kFlankingDistXLf + (long)theOpponent.xVel /
|
|
kVelocitySensitive * (long)framesAhead;
|
|
}
|
|
newZ = (long)theOpponent.zPos + kFlankingDistZ + (long)theOpponent.zVel /
|
|
kVelocitySensitive * (long)framesAhead;
|
|
}
|
|
|
|
if (newX > kMaxShort)
|
|
newX = kMaxShort;
|
|
if (newX < kMinShort)
|
|
newX = kMinShort;
|
|
if (newZ > kMaxShort)
|
|
newZ = kMaxShort;
|
|
if (newZ < kMinShort)
|
|
newZ = kMinShort;
|
|
|
|
newDirection = OctalToPoint(who, (short)newX, (short)newZ);
|
|
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== AnticipatePersonsFace
|
|
|
|
short AnticipatePersonsFace (playerType *who, short framesAhead)
|
|
|
|
{
|
|
register long newX, newZ;
|
|
short newDirection;
|
|
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
newX = (long)thePlayer.xPos + (long)thePlayer.xVel / kVelocitySensitive *
|
|
(long)framesAhead;
|
|
newZ = (long)thePlayer.zPos + (long)thePlayer.zVel / kVelocitySensitive *
|
|
(long)framesAhead;
|
|
}
|
|
else
|
|
{
|
|
newX = (long)theOpponent.xPos + (long)theOpponent.xVel / kVelocitySensitive *
|
|
(long)framesAhead;
|
|
newZ = (long)theOpponent.zPos + (long)theOpponent.zVel / kVelocitySensitive *
|
|
(long)framesAhead;
|
|
}
|
|
|
|
if (newX > kMaxShort)
|
|
newX = kMaxShort;
|
|
if (newX < kMinShort)
|
|
newX = kMinShort;
|
|
if (newZ > kMaxShort)
|
|
newZ = kMaxShort;
|
|
if (newZ < kMinShort)
|
|
newZ = kMinShort;
|
|
|
|
newDirection = OctalToPoint(who, (short)newX, (short)newZ);
|
|
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== RunTheCircleRight
|
|
|
|
short RunTheCircleRight (playerType *who)
|
|
|
|
{
|
|
short newDirection;
|
|
|
|
newDirection = who->direction;
|
|
|
|
who->turnCount++;
|
|
|
|
if ((who->turnCount == who->turnNow) || (PointingToDisaster(who)))
|
|
{
|
|
who->turnCount = 0;
|
|
newDirection ++;
|
|
if (newDirection > kLastDirection)
|
|
newDirection -= (kLastDirection + 1);
|
|
}
|
|
|
|
if ((!gameIsOver) && (NearTheGoal(who)) &&
|
|
(ExcellentDirectionalShot(who, kFacingNorthEast)))
|
|
{
|
|
newDirection = kFacingNorthEast;
|
|
who->direction = newDirection;
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== RunTheCircleLeft
|
|
|
|
short RunTheCircleLeft (playerType *who)
|
|
|
|
{
|
|
short newDirection;
|
|
|
|
newDirection = who->direction;
|
|
|
|
who->turnCount++;
|
|
|
|
if ((who->turnCount == who->turnNow) || (PointingToDisaster(who)))
|
|
{
|
|
who->turnCount = 0;
|
|
newDirection --;
|
|
if (newDirection < kFirstDirection)
|
|
newDirection += (kLastDirection + 1);
|
|
}
|
|
|
|
if ((NearTheGoal(who)) && (ExcellentDirectionalShot(who, kFacingNorthWest)))
|
|
{
|
|
newDirection = kFacingNorthWest;
|
|
who->direction = newDirection;
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
|
|
return (newDirection);
|
|
}
|
|
|
|
|
|
//======================================================== BrakeIfLeaving
|
|
|
|
void BrakeIfLeaving (playerType *who)
|
|
|
|
{
|
|
long xDelta, zDelta, newDistSquared;
|
|
|
|
xDelta = (long)who->xPos - (long)theBall.xPos;
|
|
zDelta = (long)who->zPos - (long)theBall.zPos;
|
|
|
|
newDistSquared = (xDelta * xDelta) + (zDelta * zDelta);
|
|
|
|
if (newDistSquared > oldDistSquared)
|
|
{
|
|
who->brakeApplied = TRUE;
|
|
}
|
|
|
|
oldDistSquared = newDistSquared;
|
|
}
|
|
|
|
|
|
//======================================================== BashUnlessLeaving
|
|
|
|
void BashUnlessLeaving (playerType *who)
|
|
|
|
{
|
|
#define kMaximumRammingSpeed 25600000L
|
|
long xDelta, zDelta, velocitySquared, newDistSquared;
|
|
|
|
xDelta = (long)thePlayer.xPos - (long)theOpponent.xPos;
|
|
zDelta = (long)thePlayer.zPos - (long)theOpponent.zPos;
|
|
|
|
velocitySquared = ((long)who->xVel * (long)who->xVel) +
|
|
((long)who->zVel * (long)who->zVel);
|
|
|
|
newDistSquared = (xDelta * xDelta) + (zDelta * zDelta);
|
|
|
|
if (newDistSquared < oldDistSquared)
|
|
{
|
|
if (velocitySquared < kMaximumRammingSpeed)
|
|
who->bashApplied = TRUE;
|
|
}
|
|
else
|
|
who->brakeApplied = TRUE;
|
|
|
|
oldDistSquared = newDistSquared;
|
|
}
|
|
|
|
|
|
//======================================================== GeorgeDecides
|
|
|
|
void GeorgeDecides (playerType *who)
|
|
|
|
{
|
|
short willCrouch;
|
|
|
|
if (gameIsOver)
|
|
{
|
|
who->direction = RunTheCircleRight(who);
|
|
LookUpBoardForce(who);
|
|
return;
|
|
}
|
|
|
|
switch (whosGotBall)
|
|
{
|
|
case kBallIsNotHere:
|
|
who->direction = kFacingRested;
|
|
who->posture = kStanding;
|
|
break;
|
|
case kBallRollsFreely:
|
|
if (((who->loopsBallHeld) == 0) || ((who->loopsBallHeld) > 60))
|
|
{
|
|
who->direction = DiagonalToBall(who);
|
|
LookUpBoardForce(who);
|
|
willCrouch = (short)(Ticks % 100);
|
|
if ((NearTheBall(who)) && (willCrouch < kGeorgeCrouchPercent))
|
|
who->posture = kCrouching;
|
|
else
|
|
who->posture = kStanding;
|
|
}
|
|
else
|
|
{
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
who->posture = kStanding;
|
|
}
|
|
break;
|
|
case kPlayerHasBall:
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
who->posture = kStanding;
|
|
}
|
|
else
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheDiagonalNE(who);
|
|
else
|
|
who->direction = RunTheDiagonalNW(who);
|
|
LookUpBoardForce(who);
|
|
who->posture = kCarrying;
|
|
|
|
if ((who->loopsBallHeld) < 60)
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
break;
|
|
case kOpponentHasBall:
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheDiagonalNE(who);
|
|
else
|
|
who->direction = RunTheDiagonalNW(who);
|
|
LookUpBoardForce(who);
|
|
who->posture = kCarrying;
|
|
|
|
if ((who->loopsBallHeld) < 60)
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
else
|
|
{
|
|
who->direction = OctalToPoint(who, theOpponent.xPos, theOpponent.zPos);
|
|
who->posture = kStanding;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//======================================================== MaraDecides
|
|
|
|
void MaraDecides (playerType *who)
|
|
|
|
{
|
|
short willCrouch;
|
|
|
|
#if kDemoVersion
|
|
return;
|
|
#else
|
|
if (gameIsOver)
|
|
{
|
|
who->direction = RunTheCircleRight(who);
|
|
LookUpBoardForce(who);
|
|
return;
|
|
}
|
|
|
|
switch (whosGotBall)
|
|
{
|
|
case kBallIsNotHere:
|
|
if (who->selector == kOpponentSelector)
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
else
|
|
who->direction = OctalToPoint(who, theOpponent.xPos, theOpponent.zPos);
|
|
who->posture = kStanding;
|
|
break;
|
|
case kBallRollsFreely:
|
|
if (((who->loopsBallHeld) == 0) || ((who->loopsBallHeld) > 50))
|
|
{
|
|
who->direction = DiagonalToBall(who);
|
|
LookUpBoardForce(who);
|
|
willCrouch = (short)(Ticks % 100);
|
|
if ((NearTheBall(who)) && (willCrouch < kMaraCrouchPercent))
|
|
who->posture = kCrouching;
|
|
else
|
|
who->posture = kStanding;
|
|
}
|
|
else
|
|
{
|
|
who->direction = thePlayer.direction;
|
|
who->posture = kStanding;
|
|
LookUpBoardForce(who);
|
|
}
|
|
break;
|
|
case kPlayerHasBall:
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
who->direction = thePlayer.direction;
|
|
LookUpBoardForce(who);
|
|
who->posture = kStanding;
|
|
}
|
|
else
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheDiagonalNE(who);
|
|
else
|
|
who->direction = RunTheDiagonalNW(who);
|
|
LookUpBoardForce(who);
|
|
who->posture = kCarrying;
|
|
|
|
if ((who->loopsBallHeld) < 50)
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
break;
|
|
case kOpponentHasBall:
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheDiagonalNE(who);
|
|
else
|
|
who->direction = RunTheDiagonalNW(who);
|
|
LookUpBoardForce(who);
|
|
who->posture = kCarrying;
|
|
|
|
if ((who->loopsBallHeld) < 50)
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
else
|
|
{
|
|
who->direction = theOpponent.direction;
|
|
LookUpBoardForce(who);
|
|
who->posture = kStanding;
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
//======================================================== OttoDecides
|
|
|
|
void OttoDecides (playerType *who)
|
|
|
|
{
|
|
short willCrouch;
|
|
Boolean wasBraking;
|
|
|
|
#if kDemoVersion
|
|
return;
|
|
#else
|
|
if (gameIsOver)
|
|
{
|
|
who->direction = RunTheCircleRight(who);
|
|
LookUpBoardForce(who);
|
|
return;
|
|
}
|
|
|
|
wasBraking = who->brakeApplied;
|
|
|
|
who->bashApplied = FALSE;
|
|
who->brakeApplied = FALSE;
|
|
|
|
switch (whosGotBall)
|
|
{
|
|
case kBallIsNotHere:
|
|
if (who->selector == kOpponentSelector)
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
else
|
|
who->direction = OctalToPoint(who, theOpponent.xPos, theOpponent.zPos);
|
|
who->posture = kStanding;
|
|
break;
|
|
case kBallRollsFreely:
|
|
if (((who->loopsBallHeld) == 0) || ((who->loopsBallHeld) > 40))
|
|
{
|
|
who->direction = AnticipateBall(who, 6);
|
|
LookUpBoardForce(who);
|
|
willCrouch = (short)(Ticks % 100);
|
|
if ((NearTheBall(who)) && (willCrouch < kOttoCrouchPercent))
|
|
who->posture = kCrouching;
|
|
else
|
|
who->posture = kStanding;
|
|
if (NearTheEdge(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
BashUnlessLeaving(who);
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
LookUpBoardForce(who);
|
|
if (NearTheEdge(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
who->posture = kStanding;
|
|
}
|
|
break;
|
|
case kPlayerHasBall:
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
BashUnlessLeaving(who);
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
LookUpBoardForce(who);
|
|
who->posture = kStanding;
|
|
if (NearTheEdge(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheDiagonalSmarterNE(who);
|
|
else
|
|
who->direction = RunTheDiagonalSmarterNW(who);
|
|
LookUpBoardForce(who);
|
|
who->posture = kCarrying;
|
|
|
|
if ((who->loopsBallHeld) < 40)
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
break;
|
|
case kOpponentHasBall:
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheDiagonalSmarterNE(who);
|
|
else
|
|
who->direction = RunTheDiagonalSmarterNW(who);
|
|
LookUpBoardForce(who);
|
|
who->posture = kCarrying;
|
|
|
|
if ((who->loopsBallHeld) < 40)
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
else
|
|
{
|
|
BashUnlessLeaving(who);
|
|
who->direction = OctalToPoint(who, theOpponent.xPos, theOpponent.zPos);
|
|
LookUpBoardForce(who);
|
|
who->posture = kStanding;
|
|
if (NearTheEdge(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!wasBraking && who->brakeApplied)
|
|
PlaySoundSMS(kBrakeSound);
|
|
#endif
|
|
}
|
|
|
|
|
|
//======================================================== ClaireDecides
|
|
|
|
void ClaireDecides (playerType *who)
|
|
|
|
{
|
|
short willCrouch;
|
|
|
|
#if kDemoVersion
|
|
return;
|
|
#else
|
|
if (gameIsOver)
|
|
{
|
|
who->direction = RunTheCircleRight(who);
|
|
LookUpBoardForce(who);
|
|
return;
|
|
}
|
|
|
|
switch (whosGotBall)
|
|
{
|
|
case kBallIsNotHere:
|
|
who->posture = kStanding;
|
|
if (who->selector == kOpponentSelector)
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
else
|
|
who->direction = OctalToPoint(who, theOpponent.xPos, theOpponent.zPos);
|
|
break;
|
|
case kBallRollsFreely:
|
|
if (((who->loopsBallHeld) == 0) || ((who->loopsBallHeld) > 30))
|
|
{
|
|
willCrouch = (short)(Ticks % 100);
|
|
if ((NearTheBall(who)) && (willCrouch < kClaireCrouchPercent))
|
|
who->posture = kCrouching;
|
|
else
|
|
who->posture = kStanding;
|
|
who->direction = AnticipateBall(who, 8);
|
|
LookUpBoardForce(who);
|
|
if (NearTheEdgeSmarter(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
who->direction = AnticipatePersonsFlank(who, 8);
|
|
LookUpBoardForce(who);
|
|
if (NearTheEdgeSmarter(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
who->posture = kStanding;
|
|
}
|
|
break;
|
|
case kPlayerHasBall:
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
who->posture = kStanding;
|
|
who->direction = AnticipatePersonsFlank(who, 8);
|
|
LookUpBoardForce(who);
|
|
if (NearTheEdgeSmarter(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
who->posture = kCarrying;
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheCircleRight(who);
|
|
else
|
|
who->direction = RunTheCircleLeft(who);
|
|
LookUpBoardForce(who);
|
|
|
|
if ((who->loopsBallHeld) < 30)
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
break;
|
|
case kOpponentHasBall:
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
who->posture = kCarrying;
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheCircleRight(who);
|
|
else
|
|
who->direction = RunTheCircleLeft(who);
|
|
LookUpBoardForce(who);
|
|
|
|
if ((who->loopsBallHeld) < 30)
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
else
|
|
{
|
|
who->posture = kStanding;
|
|
who->direction = AnticipatePersonsFlank(who, 8);
|
|
LookUpBoardForce(who);
|
|
if (NearTheEdgeSmarter(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
//======================================================== EazeDecides
|
|
|
|
void EazeDecides (playerType *who)
|
|
|
|
{
|
|
short willCrouch;
|
|
Boolean wasBraking;
|
|
|
|
#if kDemoVersion
|
|
return;
|
|
#else
|
|
if (gameIsOver)
|
|
{
|
|
who->direction = RunTheCircleRight(who);
|
|
LookUpBoardForce(who);
|
|
return;
|
|
}
|
|
|
|
wasBraking = who->brakeApplied;
|
|
|
|
who->bashApplied = FALSE;
|
|
who->brakeApplied = FALSE;
|
|
|
|
switch (whosGotBall)
|
|
{
|
|
case kBallIsNotHere:
|
|
who->posture = kStanding;
|
|
if (who->selector == kOpponentSelector)
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
else
|
|
who->direction = OctalToPoint(who, theOpponent.xPos, theOpponent.zPos);
|
|
break;
|
|
case kBallRollsFreely:
|
|
if (((who->loopsBallHeld) == 0) || ((who->loopsBallHeld) > 20))
|
|
{
|
|
willCrouch = (short)(Ticks % 100);
|
|
if ((NearTheBall(who)) && (willCrouch < kEazeCrouchPercent))
|
|
{
|
|
BrakeIfLeaving(who);
|
|
who->posture = kCrouching;
|
|
}
|
|
else
|
|
who->posture = kStanding;
|
|
who->direction = AnticipateBall(who, 12);
|
|
LookUpBoardForce(who);
|
|
if (NearTheEdgeSmarter(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
if (NearPerson())
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
else
|
|
who->direction = AnticipatePersonsFace(who, 12);
|
|
if (NearTheEdgeSmarter(who))
|
|
{
|
|
BrakeIfLeaving(who);
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
}
|
|
LookUpBoardForce(who);
|
|
who->posture = kStanding;
|
|
}
|
|
break;
|
|
case kPlayerHasBall:
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
who->posture = kStanding;
|
|
if (NearPerson())
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
else
|
|
who->direction = AnticipatePersonsFace(who, 12);
|
|
LookUpBoardForce(who);
|
|
if (NearTheEdgeSmarter(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
who->posture = kCarrying;
|
|
if (who->strategy == kRunDiagonal)
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheDiagonalSmartestNE(who);
|
|
else
|
|
who->direction = RunTheDiagonalSmartestNW(who);
|
|
}
|
|
else
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheCircleRight(who);
|
|
else
|
|
who->direction = RunTheCircleLeft(who);
|
|
}
|
|
LookUpBoardForce(who);
|
|
|
|
if ((who->loopsBallHeld) < 20)
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
break;
|
|
case kOpponentHasBall:
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
who->posture = kCarrying;
|
|
if (who->strategy == kRunDiagonal)
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheDiagonalSmartestNE(who);
|
|
else
|
|
who->direction = RunTheDiagonalSmartestNW(who);
|
|
}
|
|
else
|
|
{
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheCircleRight(who);
|
|
else
|
|
who->direction = RunTheCircleLeft(who);
|
|
}
|
|
LookUpBoardForce(who);
|
|
|
|
if ((who->loopsBallHeld) < 20)
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
else
|
|
{
|
|
who->posture = kStanding;
|
|
if (NearPerson())
|
|
who->direction = OctalToPoint(who, theOpponent.xPos, theOpponent.zPos);
|
|
else
|
|
who->direction = AnticipatePersonsFace(who, 12);
|
|
LookUpBoardForce(who);
|
|
if (NearTheEdgeSmarter(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!wasBraking && who->brakeApplied)
|
|
PlaySoundSMS(kBrakeSound);
|
|
#endif
|
|
}
|
|
|
|
|
|
//======================================================== TeakDecides
|
|
|
|
void TeakDecides (playerType *who)
|
|
|
|
{
|
|
short willCrouch;
|
|
Boolean wasBraking;
|
|
|
|
#if kDemoVersion
|
|
return;
|
|
#else
|
|
if (gameIsOver)
|
|
{
|
|
who->direction = RunTheCircleRight(who);
|
|
LookUpBoardForce(who);
|
|
return;
|
|
}
|
|
|
|
wasBraking = who->brakeApplied;
|
|
|
|
who->bashApplied = FALSE;
|
|
who->brakeApplied = FALSE;
|
|
|
|
switch (whosGotBall)
|
|
{
|
|
case kBallIsNotHere:
|
|
who->posture = kStanding;
|
|
if (who->selector == kOpponentSelector)
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
else
|
|
who->direction = OctalToPoint(who, theOpponent.xPos, theOpponent.zPos);
|
|
break;
|
|
case kBallRollsFreely:
|
|
if (((who->loopsBallHeld) == 0) || ((who->loopsBallHeld) > 10))
|
|
{
|
|
BrakeIfLeaving(who);
|
|
willCrouch = (short)(Ticks % 100);
|
|
if ((NearTheBall(who)) && (willCrouch < kTeakCrouchPercent))
|
|
{
|
|
who->posture = kCrouching;
|
|
}
|
|
else
|
|
{
|
|
who->posture = kStanding;
|
|
}
|
|
who->direction = AnticipateBall(who, 16);
|
|
if (NearTheEdgeSmarter(who))
|
|
{
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
who->brakeApplied = TRUE;
|
|
}
|
|
LookUpBoardForce(who);
|
|
}
|
|
else
|
|
{
|
|
if (NearPerson())
|
|
{
|
|
BashUnlessLeaving(who);
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
}
|
|
else
|
|
{
|
|
who->direction = AnticipatePersonsFace(who, 16);
|
|
}
|
|
LookUpBoardForce(who);
|
|
if (NearTheEdgeSmarter(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
who->posture = kStanding;
|
|
}
|
|
break;
|
|
case kPlayerHasBall:
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
who->posture = kStanding;
|
|
if (NearPerson())
|
|
{
|
|
BashUnlessLeaving(who);
|
|
who->direction = OctalToPoint(who, thePlayer.xPos, thePlayer.zPos);
|
|
}
|
|
else
|
|
{
|
|
who->direction = AnticipatePersonsFace(who, 16);
|
|
}
|
|
LookUpBoardForce(who);
|
|
if (NearTheEdgeSmarter(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
who->posture = kCarrying;
|
|
switch (who->strategy)
|
|
{
|
|
case kRunDiagonal:
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheDiagonalSmartestNE(who);
|
|
else
|
|
who->direction = RunTheDiagonalSmartestNW(who);
|
|
break;
|
|
case kRunCircle:
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheCircleRight(who);
|
|
else
|
|
who->direction = RunTheCircleLeft(who);
|
|
break;
|
|
}
|
|
LookUpBoardForce(who);
|
|
|
|
if ((who->loopsBallHeld) < 10)
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
break;
|
|
case kOpponentHasBall:
|
|
if (who->selector == kOpponentSelector)
|
|
{
|
|
who->posture = kCarrying;
|
|
switch (who->strategy)
|
|
{
|
|
case kRunDiagonal:
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheDiagonalSmartestNE(who);
|
|
else
|
|
who->direction = RunTheDiagonalSmartestNW(who);
|
|
break;
|
|
case kRunCircle:
|
|
if (who->whichGoal == kRightGoal)
|
|
who->direction = RunTheCircleRight(who);
|
|
else
|
|
who->direction = RunTheCircleLeft(who);
|
|
break;
|
|
}
|
|
LookUpBoardForce(who);
|
|
|
|
if ((who->loopsBallHeld) < 10)
|
|
DoPersonBallParted(who); // shoot that ball!
|
|
}
|
|
else
|
|
{
|
|
who->posture = kStanding;
|
|
if (NearPerson())
|
|
{
|
|
BashUnlessLeaving(who);
|
|
who->direction = OctalToPoint(who, theOpponent.xPos, theOpponent.zPos);
|
|
}
|
|
else
|
|
{
|
|
who->direction = AnticipatePersonsFace(who, 16);
|
|
}
|
|
LookUpBoardForce(who);
|
|
if (NearTheEdgeSmarter(who))
|
|
who->direction = OctalToPoint(who, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!wasBraking && who->brakeApplied)
|
|
PlaySoundSMS(kBrakeSound);
|
|
#endif
|
|
}
|
|
|
|
|