diff options
Diffstat (limited to 'kpacman/monster.cpp')
-rw-r--r-- | kpacman/monster.cpp | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/kpacman/monster.cpp b/kpacman/monster.cpp new file mode 100644 index 0000000..2f402b4 --- /dev/null +++ b/kpacman/monster.cpp @@ -0,0 +1,262 @@ +#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; + } +} + |