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.
263 lines
6.9 KiB
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;
|
|
}
|
|
}
|
|
|