|
|
@@ -0,0 +1,790 @@ |
|
|
#include "Actor.h" |
|
|
#include "GraphObject.h" |
|
|
#include "GameWorld.h" |
|
|
#include "StudentWorld.h" |
|
|
#include "GameConstants.h" |
|
|
#include <algorithm> |
|
|
#include <string> |
|
|
|
|
|
using namespace std; |
|
|
|
|
|
//All actors start out alive and visible |
|
|
Actor::Actor(int imageID, int startX, int startY, Direction dir, double size, unsigned int depth, StudentWorld* world) |
|
|
: GraphObject(imageID, startX, startY, dir, size, depth), m_world(world) |
|
|
{ |
|
|
m_alive = true; |
|
|
setVisible(true); |
|
|
} |
|
|
|
|
|
Actor::~Actor() |
|
|
{} |
|
|
|
|
|
StudentWorld* Actor::getWorld() |
|
|
{ |
|
|
return m_world; |
|
|
} |
|
|
|
|
|
bool Actor::isAlive() |
|
|
{ |
|
|
return m_alive; |
|
|
} |
|
|
|
|
|
void Actor::makeDead() |
|
|
{ |
|
|
m_alive = false; |
|
|
} |
|
|
|
|
|
//if Actor a is within radius of this, return true; else, return false |
|
|
bool Actor::withinRadius(Actor* a, int radius) |
|
|
{ |
|
|
for (int i = getX(); i <= getX() + radius; i++) |
|
|
{ |
|
|
for (int j = getY(); j <= getY() + radius; j++) |
|
|
{ |
|
|
for (int k = a->getX(); k <= a->getX() + radius; k++) |
|
|
{ |
|
|
for (int l = a->getY(); l <= a->getY() + radius; l++) |
|
|
{ |
|
|
if (i == k && j == l) |
|
|
{ |
|
|
return true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
return false; |
|
|
} |
|
|
|
|
|
bool Actor::isCollectible() //default all actors to non-collectible |
|
|
{ |
|
|
return false; |
|
|
} |
|
|
|
|
|
void Actor::moveInDirection(Direction dir) |
|
|
{ |
|
|
switch (dir) |
|
|
{ |
|
|
case left: |
|
|
moveTo(getX() - 1, getY()); |
|
|
break; |
|
|
case right: |
|
|
moveTo(getX() + 1, getY()); |
|
|
break; |
|
|
case up: |
|
|
moveTo(getX(), getY() + 1); |
|
|
break; |
|
|
case down: |
|
|
moveTo(getX(), getY() - 1); |
|
|
break; |
|
|
default: |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
Dirt::Dirt(int imageID, int startX, int startY, Direction dir, double size, unsigned int depth, StudentWorld* world) |
|
|
: Actor(IID_DIRT, startX, startY, dir, 0.25, 3, world) |
|
|
{} |
|
|
|
|
|
Dirt::~Dirt() |
|
|
{} |
|
|
|
|
|
void Dirt::doSomething() |
|
|
{} |
|
|
|
|
|
void Dirt::getAnnoyed() |
|
|
{} |
|
|
|
|
|
string Dirt::type() |
|
|
{ |
|
|
return "obstacle"; |
|
|
} |
|
|
|
|
|
void Dirt::loseHealth(double health) |
|
|
{} |
|
|
|
|
|
void Dirt::getHitByRock() |
|
|
{} |
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
Person::Person(int imageID, int startX, int startY, Direction dir, double size, unsigned int depth, StudentWorld* world, double health) |
|
|
:Actor(imageID, startX, startY, dir, size, depth, world), m_health(health) |
|
|
{ |
|
|
rockHit = false; |
|
|
} |
|
|
|
|
|
Person::~Person() |
|
|
{} |
|
|
|
|
|
double Person::health() |
|
|
{ |
|
|
return m_health; |
|
|
} |
|
|
|
|
|
void Person::loseHealth(double health) |
|
|
{ |
|
|
m_health -= health; |
|
|
} |
|
|
|
|
|
string Person::type() |
|
|
{ |
|
|
return "person"; |
|
|
} |
|
|
|
|
|
void Person::getHitByRock() |
|
|
{ |
|
|
rockHit = true; |
|
|
} |
|
|
|
|
|
bool Person::hitByRock() |
|
|
{ |
|
|
return rockHit; |
|
|
} |
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
Frackman::Frackman(int imageID, int startX, int startY, Direction dir, double size, unsigned int depth, StudentWorld* world, int health) |
|
|
:Person(IID_PLAYER, 30, 60, right, 1, 0, world, 10) |
|
|
{} |
|
|
|
|
|
Frackman::~Frackman() |
|
|
{} |
|
|
|
|
|
void Frackman::doSomething() |
|
|
{ |
|
|
if (!isAlive()) |
|
|
return; |
|
|
int ch; |
|
|
if (getWorld()->getKey(ch) == true) |
|
|
{ |
|
|
// user hit a key this tick! |
|
|
switch (ch) |
|
|
{ |
|
|
case KEY_PRESS_LEFT: |
|
|
if (getDirection() != left) //if the player isn't facing the direction of the pressed key, change to that direction |
|
|
{ |
|
|
setDirection(left); |
|
|
break; |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (getX() > 0 && !(getWorld()->hitsRock(this, left))) //makes sure player isn't trying to walk into a rock or boundary |
|
|
{ |
|
|
moveInDirection(left); |
|
|
} |
|
|
else |
|
|
moveTo(getX(), getY()); //if he is, run the move animation, but dont actually move anywhere |
|
|
break; |
|
|
} |
|
|
case KEY_PRESS_RIGHT: |
|
|
if (getDirection() != right) |
|
|
{ |
|
|
setDirection(right); |
|
|
break; |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (getX() < 60 && !(getWorld()->hitsRock(this, right))) |
|
|
{ |
|
|
moveInDirection(right); |
|
|
} |
|
|
else |
|
|
moveTo(getX(), getY()); |
|
|
break; |
|
|
} |
|
|
case KEY_PRESS_UP: |
|
|
if (getDirection() != up) |
|
|
{ |
|
|
setDirection(up); |
|
|
break; |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (getY() < 60 && !(getWorld()->hitsRock(this, up))) |
|
|
{ |
|
|
moveInDirection(up); |
|
|
} |
|
|
else |
|
|
moveTo(getX(), getY()); |
|
|
break; |
|
|
} |
|
|
case KEY_PRESS_DOWN: |
|
|
if (getDirection() != down) |
|
|
{ |
|
|
setDirection(down); |
|
|
break; |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (getY() > 0 && !(getWorld()->hitsRock(this, down))) |
|
|
{ |
|
|
moveInDirection(down); |
|
|
} |
|
|
else |
|
|
moveTo(getX(), getY()); |
|
|
break; |
|
|
} |
|
|
case KEY_PRESS_SPACE: |
|
|
if (getWorld()->countWater() > 0) |
|
|
{ |
|
|
getWorld()->shootWater(getDirection(), getX(), getY()); |
|
|
} |
|
|
break; |
|
|
case KEY_PRESS_TAB: |
|
|
getWorld()->dropGold(getX(), getY()); |
|
|
break; |
|
|
case 90: |
|
|
case 122: |
|
|
getWorld()->scan(); |
|
|
break; |
|
|
case KEY_PRESS_ESCAPE: |
|
|
makeDead(); |
|
|
break; |
|
|
default: |
|
|
return; |
|
|
} |
|
|
bool soundPlayed = false; //checks if sound for digging dirt has been played |
|
|
for (int i = getX(); i < getX() + 4; i++) |
|
|
{ |
|
|
for (int j = getY(); j < getY() + 4; j++) |
|
|
{ |
|
|
if (getWorld()->isDirt(i, j)) |
|
|
{ |
|
|
getWorld()->removeDirt(i, j); //removes dirt in all the space the player takes up after moving |
|
|
if (soundPlayed == false) |
|
|
{ |
|
|
getWorld()->playSound(SOUND_DIG); //ensures the dig sound is played only once |
|
|
soundPlayed = true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
void Frackman::getAnnoyed() |
|
|
{ |
|
|
if (hitByRock()) |
|
|
makeDead(); |
|
|
else |
|
|
loseHealth(2); //if Frackman gets annoyed by a Protestor, lose 2 health |
|
|
if (health() <= 0) //Frackman dies once health goes to 0 or below |
|
|
{ |
|
|
makeDead(); |
|
|
getWorld()->playSound(SOUND_PLAYER_GIVE_UP); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
Boulder::Boulder(int imageID, int startX, int startY, Direction dir, double size, unsigned int depth, StudentWorld* world) |
|
|
:Actor(IID_BOULDER, startX, startY, down, 1.0, 1, world) |
|
|
{ |
|
|
m_status = "stable"; //boulders start off stable |
|
|
countWaiting = 0; //keeps track of ticks when it will be in waiting state |
|
|
for (int i = getX(); i < getX() + 4; i++) |
|
|
{ |
|
|
for (int j = getY(); j < getY() + 4; j++) |
|
|
{ |
|
|
getWorld()->removeDirt(i, j); //remove all dirt in the spaces where boulders are |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
Boulder::~Boulder() |
|
|
{} |
|
|
|
|
|
void Boulder::doSomething() |
|
|
{ |
|
|
if (!isAlive()) |
|
|
return; |
|
|
if (m_status == "stable") |
|
|
{ |
|
|
for (int i = getX(); i < getX() + 4; i++) |
|
|
{ |
|
|
if (getWorld()->isDirt(i, getY() - 1)) //if there is still dirt below the boulder, do nothing |
|
|
{ |
|
|
return; |
|
|
} |
|
|
} |
|
|
m_status = "waiting"; //else switch to waiting state |
|
|
return; |
|
|
} |
|
|
if (m_status == "waiting") |
|
|
{ |
|
|
countWaiting++; //for every tick in waiting state, add one to countWaiting |
|
|
if (countWaiting == 30) //once it hits 30, start falling |
|
|
{ |
|
|
getWorld()->playSound(SOUND_FALLING_ROCK); |
|
|
m_status = "falling"; |
|
|
return; |
|
|
} |
|
|
return; |
|
|
} |
|
|
if (m_status == "falling") //keep falling until it hits an obstacle or boundary |
|
|
{ |
|
|
moveInDirection(down); |
|
|
getWorld()->collide(this, 3); |
|
|
if (getY() == 0) |
|
|
{ |
|
|
makeDead(); |
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
void Boulder::getAnnoyed() |
|
|
{} |
|
|
|
|
|
string Boulder::status() |
|
|
{ |
|
|
return m_status; |
|
|
} |
|
|
|
|
|
string Boulder::type() |
|
|
{ |
|
|
return "rock"; |
|
|
} |
|
|
|
|
|
void Boulder::loseHealth(double health) |
|
|
{} |
|
|
|
|
|
void Boulder::getHitByRock() |
|
|
{} |
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
Squirt::Squirt(int imageID, int startX, int startY, Direction dir, double size, unsigned int depth, StudentWorld* world) |
|
|
: Actor(IID_WATER_SPURT, startX, startY, dir, 1.0, 1, world) |
|
|
{ |
|
|
m_health = 4; //squirts can only travel 4 squares |
|
|
} |
|
|
|
|
|
Squirt::~Squirt() |
|
|
{} |
|
|
|
|
|
void Squirt::doSomething() |
|
|
{ |
|
|
Direction dir = getDirection(); |
|
|
if (!isAlive()) |
|
|
return; |
|
|
getWorld()->collide(this, 3); //checks if the squirt collides with anything |
|
|
if (isAlive()) //if it doesn't, just move in the target direction |
|
|
{ |
|
|
moveInDirection(dir); |
|
|
m_health--; //lose one health every time it moves |
|
|
if (m_health == 0) |
|
|
makeDead(); |
|
|
} |
|
|
} |
|
|
|
|
|
void Squirt::getAnnoyed() |
|
|
{} |
|
|
|
|
|
string Squirt::type() |
|
|
{ |
|
|
return "water"; |
|
|
} |
|
|
|
|
|
void Squirt::loseHealth(double health) |
|
|
{} |
|
|
|
|
|
void Squirt::getHitByRock() |
|
|
{} |
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
Goodie::Goodie(int imageID, int startX, int startY, Direction dir, double size, unsigned int depth, StudentWorld* world) |
|
|
:Actor(imageID, startX, startY, dir, size, depth, world) |
|
|
{ |
|
|
//setVisible(false); //all goodies are invisible |
|
|
} |
|
|
|
|
|
Goodie::~Goodie() |
|
|
{} |
|
|
|
|
|
bool Goodie::isCollectible() //all goodies are collectible |
|
|
{ |
|
|
return true; |
|
|
} |
|
|
|
|
|
void Goodie::getHitByRock() |
|
|
{} |
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
Barrel::Barrel(int imageID, int startX, int startY, Direction dir, double size, unsigned int depth, StudentWorld* world) |
|
|
:Goodie(IID_BARREL, startX, startY, right, 1.0, 2, world) |
|
|
{ |
|
|
//setVisible(true); |
|
|
} |
|
|
|
|
|
Barrel::~Barrel() |
|
|
{} |
|
|
|
|
|
void Barrel::doSomething() |
|
|
{ |
|
|
if (!isAlive()) |
|
|
return; |
|
|
getWorld()->detectGoodie(this); |
|
|
getWorld()->collectGoodie(this); |
|
|
} |
|
|
|
|
|
void Barrel::getAnnoyed() |
|
|
{} |
|
|
|
|
|
void Barrel::loseHealth(double health) |
|
|
{} |
|
|
|
|
|
string Barrel::type() |
|
|
{ |
|
|
return "oil"; |
|
|
} |
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
Nugget::Nugget(int imageID, int startX, int startY, Direction dir, double size, unsigned int depth, StudentWorld* world) |
|
|
:Goodie(IID_GOLD, startX, startY, right, 1.0, 2, world) |
|
|
{ |
|
|
m_discovered = false; |
|
|
m_lifetime = 100; |
|
|
} |
|
|
|
|
|
Nugget::~Nugget() |
|
|
{} |
|
|
|
|
|
void Nugget::doSomething() |
|
|
{ |
|
|
if (!isAlive()) |
|
|
return; |
|
|
if (!isDiscovered()) |
|
|
{ |
|
|
getWorld()->detectGoodie(this); |
|
|
getWorld()->collectGoodie(this); |
|
|
} |
|
|
if (isDiscovered()) |
|
|
{ |
|
|
m_lifetime--; |
|
|
if (m_lifetime == 0) |
|
|
makeDead(); |
|
|
} |
|
|
} |
|
|
|
|
|
void Nugget::getAnnoyed() |
|
|
{} |
|
|
|
|
|
void Nugget::loseHealth(double health) |
|
|
{} |
|
|
|
|
|
string Nugget::type() |
|
|
{ |
|
|
return "gold"; |
|
|
} |
|
|
|
|
|
bool Nugget::isDiscovered() |
|
|
{ |
|
|
return m_discovered; |
|
|
} |
|
|
|
|
|
void Nugget::setDiscovered() |
|
|
{ |
|
|
m_discovered = true; |
|
|
} |
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
Sonar::Sonar(int imageID, int startX, int startY, Direction dir, double size, unsigned int depth, StudentWorld* world) |
|
|
:Goodie(IID_SONAR, startX, startY, right, 1.0, 2, world) |
|
|
{ |
|
|
setVisible(true); |
|
|
m_lifetime = 300 - 10 * (getWorld()->getLevel()); |
|
|
if (m_lifetime < 100) |
|
|
m_lifetime = 100; |
|
|
} |
|
|
|
|
|
Sonar::~Sonar() |
|
|
{} |
|
|
|
|
|
void Sonar::doSomething() |
|
|
{ |
|
|
if (!isAlive()) |
|
|
return; |
|
|
getWorld()->collectGoodie(this); |
|
|
m_lifetime--; |
|
|
if (m_lifetime == 0) |
|
|
makeDead(); |
|
|
} |
|
|
|
|
|
void Sonar::getAnnoyed() |
|
|
{} |
|
|
|
|
|
void Sonar::loseHealth(double health) |
|
|
{} |
|
|
|
|
|
string Sonar::type() |
|
|
{ |
|
|
return "sonar"; |
|
|
} |
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
Pool::Pool(int imageID, int startX, int startY, Direction dir, double size, unsigned int depth, StudentWorld* world) |
|
|
: Goodie(IID_WATER_POOL, startX, startY, right, 1.0, 2, world) |
|
|
{ |
|
|
setVisible(true); |
|
|
m_lifetime = max(100 , 300 - 10 * static_cast<int>(getWorld()->getLevel())); |
|
|
} |
|
|
|
|
|
Pool::~Pool() |
|
|
{} |
|
|
|
|
|
void Pool::doSomething() |
|
|
{ |
|
|
if (!isAlive()) |
|
|
return; |
|
|
getWorld()->collectGoodie(this); |
|
|
m_lifetime--; |
|
|
if (m_lifetime == 0) |
|
|
makeDead(); |
|
|
} |
|
|
|
|
|
void Pool::getAnnoyed() |
|
|
{} |
|
|
|
|
|
void Pool::loseHealth(double health) |
|
|
{} |
|
|
|
|
|
string Pool::type() |
|
|
{ |
|
|
return "pool"; |
|
|
} |
|
|
|
|
|
////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
Protester::Protester(int imageID, int startX, int startY, Direction dir, double size, unsigned int depth, StudentWorld* world, double health) |
|
|
: Person(IID_PROTESTER, 60, 60, left, 1.0, 0, world, 5.0) |
|
|
{ |
|
|
resetTravelDistance(); |
|
|
resetWaitTicks(); |
|
|
resetShoutTicks(); |
|
|
turningTicks = 0; |
|
|
m_state = "active"; |
|
|
} |
|
|
|
|
|
Protester::~Protester() |
|
|
{} |
|
|
|
|
|
void Protester::doSomething() |
|
|
{ |
|
|
if (!isAlive()) |
|
|
return; |
|
|
if (m_state == "resting") //when resting, wait until can be active again |
|
|
{ |
|
|
waitingTicks--; |
|
|
if (waitingTicks <= 0) |
|
|
m_state = "active"; |
|
|
} |
|
|
if (m_state == "dead end") |
|
|
{ |
|
|
travelDistance = 0; //when travel distance is 0, calls getNewDirection |
|
|
m_state = "active"; |
|
|
return; //returns so protester acts on the next tick |
|
|
} |
|
|
if (m_state == "active") |
|
|
{ |
|
|
if (getWorld()->canShout(this, getDirection()) && shoutingTicks <= 0) //if Protester is next to Frackman and is ready to shout |
|
|
{ |
|
|
getWorld()->frackOff(this); |
|
|
resetShoutTicks(); |
|
|
} |
|
|
else if (getWorld()->hasLineOfSight(this) != none) //else if Protester cant shout, but still has line of sight |
|
|
{ |
|
|
travelDistance = 0; |
|
|
moveTowardPlayer(getWorld()->hasLineOfSight(this)); |
|
|
} |
|
|
else if (travelDistance <= 0) //else if no line of sight, and travelDistance is non-positive |
|
|
{ |
|
|
setDirection(getNewDirection()); //sets new random direction |
|
|
resetTravelDistance(); |
|
|
moveInDirection(getDirection()); //moves in new direction |
|
|
} |
|
|
else if (canTurn() && getTurnTicks() <= 0) //if travelDistance is positive, and at an intersection |
|
|
{ |
|
|
setDirection(turns()); //sets new random direction |
|
|
resetTravelDistance(); |
|
|
resetTurnTicks(); |
|
|
moveInDirection(getDirection()); //moves in new direction |
|
|
} |
|
|
else if (!getWorld()->pathValid(this, getDirection())) |
|
|
{ |
|
|
m_state = "dead end"; |
|
|
} |
|
|
else |
|
|
{ |
|
|
cout << "move" << endl; |
|
|
if (getWorld()->pathValid(this, getDirection())) |
|
|
{ |
|
|
moveInDirection(getDirection()); |
|
|
} |
|
|
} |
|
|
shoutingTicks--; |
|
|
turningTicks--; |
|
|
resetWaitTicks(); |
|
|
if (m_state != "dead end") |
|
|
m_state = "resting"; |
|
|
} |
|
|
} |
|
|
|
|
|
void Protester::getAnnoyed() |
|
|
{ |
|
|
if (m_state == "give up") |
|
|
{ |
|
|
return; |
|
|
} |
|
|
|
|
|
if (hitByRock()) |
|
|
{ |
|
|
loseHealth(100.0); |
|
|
getWorld()->increaseScore(500); |
|
|
waitingTicks = 0; |
|
|
m_state = "give up"; |
|
|
getWorld()->playSound(SOUND_PROTESTER_GIVE_UP); |
|
|
} |
|
|
else |
|
|
{ |
|
|
loseHealth(2.0); |
|
|
if (health() <= 0) |
|
|
{ |
|
|
getWorld()->increaseScore(100); |
|
|
m_state = "give up"; |
|
|
getWorld()->playSound(SOUND_PROTESTER_GIVE_UP); |
|
|
} |
|
|
else |
|
|
{ |
|
|
getWorld()->playSound(SOUND_PROTESTER_ANNOYED); |
|
|
waitingTicks = max(50, 100 - (static_cast<int>(getWorld()->getLevel()) * 10)); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
string Protester::type() |
|
|
{ |
|
|
return "protester"; |
|
|
} |
|
|
|
|
|
int Protester::getShoutTicks() |
|
|
{ |
|
|
return shoutingTicks; |
|
|
} |
|
|
|
|
|
int Protester::getTurnTicks() |
|
|
{ |
|
|
return turningTicks; |
|
|
} |
|
|
|
|
|
void Protester::resetWaitTicks() |
|
|
{ |
|
|
waitingTicks = max(0, 3 - (static_cast<int>(getWorld()->getLevel()) / 4)); |
|
|
} |
|
|
|
|
|
void Protester::resetShoutTicks() |
|
|
{ |
|
|
shoutingTicks = 15; |
|
|
} |
|
|
|
|
|
void Protester::resetTurnTicks() |
|
|
{ |
|
|
turningTicks = 200; |
|
|
} |
|
|
|
|
|
void Protester::resetTravelDistance() |
|
|
{ |
|
|
travelDistance = rand() % 52 + 8; |
|
|
} |
|
|
|
|
|
void Protester::moveTowardPlayer(Direction dir) |
|
|
{ |
|
|
if (dir == getDirection()) |
|
|
moveInDirection(dir); |
|
|
else |
|
|
{ |
|
|
setDirection(dir); |
|
|
moveInDirection(dir); |
|
|
} |
|
|
} |
|
|
|
|
|
bool Protester::canTurn() |
|
|
{ |
|
|
if (getDirection() == left || getDirection() == right) |
|
|
{ |
|
|
if (getWorld()->pathValid(this, up) || getWorld()->pathValid(this, down)) |
|
|
{ |
|
|
return true; |
|
|
} |
|
|
return false; |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (getWorld()->pathValid(this, left) || getWorld()->pathValid(this, right)) |
|
|
{ |
|
|
return true; |
|
|
} |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
GraphObject::Direction Protester::turns() |
|
|
{ |
|
|
Direction dir = getDirection(); |
|
|
Direction newDir = getNewDirection(); |
|
|
switch (dir) |
|
|
{ |
|
|
case left: |
|
|
if (newDir == right) |
|
|
return turns(); |
|
|
case right: |
|
|
if (newDir == left) |
|
|
return turns(); |
|
|
case up: |
|
|
if (newDir == down) |
|
|
return turns(); |
|
|
case down: |
|
|
if (newDir == up) |
|
|
return turns(); |
|
|
default: |
|
|
return dir; |
|
|
} |
|
|
} |
|
|
|
|
|
GraphObject::Direction Protester::getNewDirection() |
|
|
{ |
|
|
int random = rand() % 3; |
|
|
if (random == 0 && getWorld()->pathValid(this, left)) |
|
|
{ |
|
|
return left; |
|
|
} |
|
|
if (random == 1 && getWorld()->pathValid(this, right)) |
|
|
{ |
|
|
return right; |
|
|
} |
|
|
if (random == 2 && getWorld()->pathValid(this, up)) |
|
|
{ |
|
|
return up; |
|
|
} |
|
|
if (random == 3 && getWorld()->pathValid(this, down)) |
|
|
{ |
|
|
return down; |
|
|
} |
|
|
else |
|
|
return getNewDirection(); |
|
|
} |
|
|
|
|
|
bool Protester::facingEdge() |
|
|
{ |
|
|
return false; |
|
|
} |