Pararena2/Sources/Computer.c

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
}