summaryrefslogtreecommitdiffstats
path: root/kpacman/monster.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kpacman/monster.cpp')
-rw-r--r--kpacman/monster.cpp262
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;
+ }
+}
+