You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepacman/tdepacman/monster.cpp

263 lines
6.9 KiB

#include "monster.h"
#include "board.h"
Monster::Monster(Board *b, int mid)
{
board = b;
ID = mid;
setREM(0);
setHarmless(0, 0, 0);
setArrested(0, 0);
setFreedom(board->position(prisonexit));
if (mid == 0)
setPrison(board->position(prisonentry));
else
setPrison(board->position(monsterhome, mid));
actualPosition = lastPosition = OUT;
feetPosition = 0;
IQ = 0;
maxBodyPixmaps = 0;
maxEyesPixmaps = 0;
}
void Monster::setMaxPixmaps(int maxBody, int maxEyes)
{
if (feetPosition >= (maxBody/10))
feetPosition = 0;
maxBodyPixmaps = maxBody;
maxEyesPixmaps = maxEyes;
}
void Monster::setArrested(int ticks, int duration)
{
actualState = dangerous;
pauseDuration = ticks;
pause = 0;
arrestDuration = arrestLeft = duration;
arrestPause = ticks;
harmlessLeft = 0;
}
void Monster::setDangerous(int ticks, int iq)
{
actualState = dangerous;
pauseDuration = ticks;
pause = 0;
dangerousPause = ticks;
harmlessLeft = 0;
IQ = iq;
}
void Monster::setHarmless(int ticks, int hDuration, int wDuration)
{
actualState = harmless;
pauseDuration = ticks;
pause = 0;
harmlessDuration = harmlessLeft = hDuration;
warningDuration = wDuration;
}
void Monster::setREM(int ticks)
{
actualState = rem;
pauseDuration = ticks;
pause = 0;
}
void Monster::setPosition(int pos)
{
board->reset(lastPosition, monster, ID); // reset old position on the board
actualPosition = lastPosition = pos; // set position of monster
board->set(actualPosition, monster, ID);
feetPosition = 0;
}
void Monster::setPrison(int pos)
{
prisonPosition = pos;
}
void Monster::setFreedom(int pos)
{
freedomPosition = pos;
}
void Monster::setDirection(int dir)
{
if (dir == X)
lastDirection = actualDirection;
actualDirection = dir;
}
monsterState Monster::state()
{
return actualState;
}
int Monster::position()
{
return actualPosition;
}
int Monster::direction()
{
return actualDirection;
}
int Monster::id()
{
return ID;
}
bool Monster::move()
{
if (arrestLeft > 1)
arrestLeft--;
if (harmlessLeft > 0) {
harmlessLeft--;
if (harmlessLeft == 0 && actualState == harmless) {
actualState = dangerous;
pauseDuration = dangerousPause;
}
}
if (pause-- > 0)
return FALSE;
else
pause = pauseDuration;
if (actualPosition == OUT)
return FALSE;
if (actualDirection == X) {
if (++feetPosition >= (maxBodyPixmaps/10))
feetPosition = 0;
return TRUE;
}
lastPosition = actualPosition;
int d = actualDirection;
if (arrestLeft > 1) { // during the arrest, only up and down
if (!board->isWay(actualPosition, d, empty) &&
!board->isWay(actualPosition, d, tunnel))
d = board->turn(actualDirection);
}
if (arrestLeft == 1) { // going out of the prison
if (((d == W || d == E) &&
board->x(actualPosition) == board->x(freedomPosition)) ||
((d == S || d == N) &&
board->y(actualPosition) == board->y(freedomPosition)) ||
board->isWay(actualPosition, d, brick) ||
board->isWay(actualPosition, d, prison)) {
d = board->closeup(actualPosition, d, freedomPosition);
}
while (board->isWay(actualPosition, d, brick) ||
board->isWay(actualPosition, d, prison)) {
if (d == actualDirection)
d = rand() % 4;
else
d = actualDirection;
}
if (actualState == dangerous)
pauseDuration = dangerousPause;
}
if (arrestLeft == 0)
if (actualState == rem) { // on the way to prison
d = board->closeup(actualPosition, d, prisonPosition);
while (board->isWay(actualPosition, d, brick) ||
board->isWay(actualPosition, d, prison)) {
if (d != actualDirection) // if new direction is not possible,
d = actualDirection; // try current direction first.
else
d = rand() % 4;
}
} else { // dangerous or harmless movement
if (rand() % (int) ((190-IQ)/10) == 0) {
d = board->closeup(actualPosition, d, board->position(pacman));
if (actualState == harmless)
d = board->turn(d);
} else
do // try new direction, but not the opposite
d = rand() % 4; // direction, to prevent hectic movement.
while (d == board->turn(actualDirection));
while ((!board->isWay(actualPosition, d, empty) &&
!board->isWay(actualPosition, d, tunnel)) ||
d == board->turn(actualDirection)) {
if (d != actualDirection) // if new direction is not possible,
d = actualDirection; // try current direction first.
else
d = rand() % 4;
}
}
actualDirection = d;
actualPosition = board->move(actualPosition, actualDirection);
if (arrestLeft == 1 && actualPosition == freedomPosition)
arrestLeft = 0;
if (actualState == rem && actualPosition == prisonPosition) {
actualState = dangerous;
pauseDuration = arrestPause;
arrestLeft = arrestDuration+1;
actualDirection = S;
}
if (actualPosition != lastPosition) {
board->reset(lastPosition, monster, ID);
board->set(actualPosition, monster, ID);
}
if (++feetPosition >= (maxBodyPixmaps/10))
feetPosition = 0;
return TRUE;
}
int Monster::body()
{
if (actualState == rem || actualPosition == OUT)
return -1;
else
if (actualState == harmless)
if (harmlessLeft > warningDuration ||
harmlessLeft % (int) (warningDuration/4.5) > (int) (warningDuration/9))
return ((maxBodyPixmaps/10)*8)+feetPosition;
else
return ((maxBodyPixmaps/10)*9)+feetPosition;
else
return ((maxBodyPixmaps/10)*ID)+feetPosition;
}
int Monster::eyes()
{
if (actualState == harmless || actualPosition == OUT)
return -1;
else
switch (actualDirection) {
case N : return 0;
case E : return 1;
case S : return 2;
case W : return 3;
case X : switch (lastDirection) {
case N : return 0;
case E : return 1;
case S : return 2;
default : return 3;
}
default : return -1;
}
}