Commit 1e268056 authored by Ian Wadham's avatar Ian Wadham

Make the animation smoother when falling and standing on an enemy. Fix some...

Make the animation smoother when falling and standing on an enemy. Fix some problems in the search strategy code for the KGoldrunner rules. Finalise the KGrTimer code. Remove a redundant show() of the main window. Avoid mixing QAction, KAction and setShortcut() in the GUI. Make the editor reference and create games on the main game-list, not a copy. Add a view to KGrGameIO, for error messages. Update the debugging output for hero's and enemies' states. Fix some minor memory leaks. Remove the printRules() method, needed only during testing.

svn path=/trunk/KDE/kdegames/kgoldrunner/; revision=980574
parent 44f3edb1
......@@ -168,10 +168,6 @@ KGoldrunner::KGoldrunner()
void KGoldrunner::KGoldrunner_2()
{
kDebug() << "Entered constructor extension ...";
// NOW paint the main widget (title, menu, status bar, blank playfield).
// TODO - Necessary? It has just been done in main.cpp ... show();
show();
kDebug() << "Main Window show() done here ...";
// Queue a call to the "initGame" method. This renders and paints the
// initial graphics, but only AFTER the initial main-window resize events
......@@ -199,7 +195,7 @@ void KGoldrunner::setupActions()
// Load Saved Game...
// --------------------------
QAction * a = KStandardGameAction::gameNew (gameMapper, SLOT(map()), this);
KAction * a = KStandardGameAction::gameNew (gameMapper, SLOT(map()), this);
actionCollection()->addAction (a->objectName(), a);
gameMapper->setMapping (a, NEW);
a->setText (i18n ("&New Game..."));
......@@ -307,7 +303,7 @@ void KGoldrunner::setupActions()
// Edit a Level...
// --------------------------
QAction * ed = editAction ("create_level", CREATE_LEVEL,
KAction * ed = editAction ("create_level", CREATE_LEVEL,
i18n ("&Create Level"),
i18n ("Create level."),
i18n ("Create a completely new level."));
......@@ -544,21 +540,18 @@ void KGoldrunner::setupActions()
keyControl ("show_enemy_6", i18n ("Show Enemy") + '6', Qt::Key_6, ENEMY_6);
}
QAction * KGoldrunner::gameAction (const QString & name,
KAction * KGoldrunner::gameAction (const QString & name,
const int code,
const QString & text,
const QString & toolTip,
const QString & whatsThis,
const QKeySequence & key)
{
QAction * ga = actionCollection()->addAction (name);
KAction * ga = actionCollection()->addAction (name);
ga->setText (text);
ga->setToolTip (toolTip);
ga->setWhatsThis (whatsThis);
if (! key.isEmpty()) {
// TODO - Shortcut for KAction "xxx" set with QShortcut::setShortcut()!
// TODO - See KAction documentation. [Runtime ERROR message]
// TODO - (xxx = kill_hero, increase_speed, decrease_speed)
ga->setShortcut (key);
}
connect (ga, SIGNAL (triggered (bool)), tempMapper, SLOT (map()));
......@@ -566,13 +559,13 @@ QAction * KGoldrunner::gameAction (const QString & name,
return ga;
}
QAction * KGoldrunner::editAction (const QString & name,
KAction * KGoldrunner::editAction (const QString & name,
const int code,
const QString & text,
const QString & toolTip,
const QString & whatsThis)
{
QAction * ed = actionCollection()->addAction (name);
KAction * ed = actionCollection()->addAction (name);
ed->setText (text);
ed->setToolTip (toolTip);
ed->setWhatsThis (whatsThis);
......@@ -641,8 +634,6 @@ void KGoldrunner::setupThemes()
KConfigGroup gameGroup (KGlobal::config(), "KDEGame"); // Get prev theme.
// TODO change this to a ThemeName (or simply Theme) option. The theme
// should be searched in the themeFilepaths defined above.
QString currentThemeFilepath = gameGroup.readEntry ("ThemeFilepath", "");
kDebug()<< "Config() Theme" << currentThemeFilepath;
......@@ -977,7 +968,7 @@ void KGoldrunner::setupEditToolbarActions()
game, SLOT (editToolbarActions (int)));
tempMapper = editToolbarMapper;
QAction * ed = editAction ("edit_hint", EDIT_HINT,
KAction * ed = editAction ("edit_hint", EDIT_HINT,
i18n ("Edit Name/Hint"),
i18n ("Edit level name or hint"),
i18n ("Edit text for the name or hint "
......
......@@ -35,7 +35,6 @@ const int L_LEVEL = 15;
#include <kstandarddirs.h>
#include "kgrglobals.h"
class QAction;
class QSignalMapper;
class KAction;
class KToggleAction;
......@@ -120,11 +119,11 @@ private:
QSignalMapper * tempMapper; // Temporary pointer.
QAction * gameAction (const QString & name, const int code,
KAction * gameAction (const QString & name, const int code,
const QString & text, const QString & toolTip,
const QString & whatsThis, const QKeySequence & key);
QAction * editAction (const QString & name, const int code,
KAction * editAction (const QString & name, const int code,
const QString & text, const QString & toolTip,
const QString & whatsThis);
......@@ -153,16 +152,16 @@ private:
QString systemDataDir; // Where the system levels are stored.
QString userDataDir; // Where the user levels are stored.
QAction * saveGame; // Save game, level, lives and score.
KAction * saveGame; // Save game, level, lives and score.
// A KAction is needed here, to get access to KShortcut::setAlternate().
KAction * myPause; // Pause or resume the game.
QAction * hintAction; // Display a hint, if available.
QAction * killHero; // Kill hero (disabled during edits).
QAction * highScore; // High scores (disabled during edits).
KAction * hintAction; // Display a hint, if available.
KAction * killHero; // Kill hero (disabled during edits).
KAction * highScore; // High scores (disabled during edits).
QAction * saveEdits; // Save a level that has been edited.
KAction * saveEdits; // Save a level that has been edited.
KToolBar * editToolbar; // Toolbar for creating/editing levels.
};
......
......@@ -76,7 +76,7 @@ KGrCanvas::KGrCanvas (QWidget * parent, const double scale,
scaleStep = STEP; // Initial scale is 1:1.
baseScale = scaleStep;
baseFontSize = fontInfo().pointSize() + 2;
// IDW baseFontSize = fontInfo().pointSize() + 2;
scaleStep = (int) ((scale * STEP) + 0.05);
kDebug() << "Scale" << scale << "Scaled Step" << scaleStep;
......@@ -680,7 +680,6 @@ void KGrCanvas::deleteSprite (const int spriteId)
// Dug-brick sprite erased: restore the tile that was at that location.
paintCell ((loc.x()/bgw) + 1, (loc.y()/bgh) + 1, BRICK, 0);
}
// kDebug() << "Sprite ID" << spriteId << "emptySprites" << emptySprites;
}
void KGrCanvas::deleteAllSprites()
......
......@@ -376,7 +376,7 @@ bool KGrEditor::moveLevelFile (int pGameIndex, int level)
filePath1 = getLevelFilePath (gameList.at (fromC), fromL);
filePath2 = filePath1;
filePath2 = filePath2.append (".tmp");
if (! KGrGameIO::safeRename (filePath1, filePath2)) {
if (! KGrGameIO::safeRename (view, filePath1, filePath2)) {
return false;
}
......@@ -413,7 +413,7 @@ bool KGrEditor::moveLevelFile (int pGameIndex, int level)
// Rename the saved "fromL" file to become "toL".
filePath1 = getLevelFilePath (gameList.at (toC), toL);
KGrGameIO::safeRename (filePath2, filePath1); // IDW
KGrGameIO::safeRename (view, filePath2, filePath1);
editLevel = toL;
emit showLevel (editLevel);
......@@ -423,7 +423,6 @@ bool KGrEditor::moveLevelFile (int pGameIndex, int level)
bool KGrEditor::deleteLevelFile (int pGameIndex, int level)
{
// TODO - Coukd we delete a system level? There appears to be no check.
int action = SL_DELETE;
gameIndex = pGameIndex;
......@@ -510,6 +509,7 @@ bool KGrEditor::editGame (int pGameIndex)
n = gameIndex;
}
bool result = false;
KGrECDialog * ec = new KGrECDialog (action, n, gameList, view);
while (ec->exec() == QDialog::Accepted) { // Loop until valid.
......@@ -580,9 +580,11 @@ bool KGrEditor::editGame (int pGameIndex)
KGrGameData * gameData = 0;
if (action == SL_CR_GAME) {
// Create empty game data and add it to the list.
// Create empty game data and add it to the main list in KGrGame.
gameData = new KGrGameData();
gameList.append (gameData);
gameIndex = gameList.count() - 1;
editLevel = 1;
// Set the initial values for a new game.
gameData->owner = USER;
......@@ -603,11 +605,12 @@ bool KGrEditor::editGame (int pGameIndex)
gameData->about = ec->getAboutText().toUtf8();
saveGameData (USER);
result = true; // Successful create/edit.
break; // All done now.
}
delete ec;
return true;
return result;
}
/******************************************************************************/
......@@ -756,7 +759,7 @@ bool KGrEditor::reNumberLevels (int cIndex, int first, int last, int inc)
while (i != n) {
file1 = getLevelFilePath (gameList.at (cIndex), i);
file2 = getLevelFilePath (gameList.at (cIndex), i - step);
if (! KGrGameIO::safeRename (file1, file2)) {
if (! KGrGameIO::safeRename (view, file1, file2)) {
return (false);
}
i = i + step;
......
......@@ -187,7 +187,9 @@ private:
KGrGameIO * io; // I/O object for reading level-data.
QString systemDataDir;
QString userDataDir;
QList<KGrGameData *> gameList;
// Will REFERENCE the main list in KGrGame, allowing KGrEditor to add games.
QList<KGrGameData *> & gameList;
bool mouseMode; // Flag to set up keyboard OR mouse control.
bool editMode; // Flag to change keyboard and mouse functions.
......
......@@ -102,9 +102,16 @@ KGrGame::KGrGame (KGrCanvas * theView,
KGrGame::~KGrGame()
{
while (! gameList.isEmpty())
while (! gameList.isEmpty()) {
delete gameList.takeFirst();
}
delete randomGen;
if (levelPlayer) {
delete levelPlayer;
}
if (recording) {
delete recording;
}
}
// Flags to control author's debugging aids.
......@@ -301,8 +308,7 @@ void KGrGame::editActions (const int action)
int game = gameIndex, lev = level;
editor->getGameAndLevel (game, lev);
kDebug() << "Game used" << gameList.at(gameIndex)->name << "level" << level;
kDebug() << "Editor used" << gameList.at(game)->name << "level" << lev;
if (((game != gameIndex) || (lev != level)) && (lev != 0)) {
gameIndex = game;
prefix = gameList.at (gameIndex)->prefix;
......@@ -1009,6 +1015,7 @@ void KGrGame::goUpOneLevel()
freeze (ProgramPause, false);
level = 0; // Game completed: display the "ENDE" screen.
// TODO - Do NOT go on and save game-prefix and level 0 in KConfig.
}
else {
level++; // Go up one level.
......@@ -1315,7 +1322,7 @@ void KGrGame::saveGame() // Save game ID, score and level.
file2.close();
if (KGrGameIO::safeRename (userDataDir+"savegame.tmp",
if (KGrGameIO::safeRename (view, userDataDir+"savegame.tmp",
userDataDir+"savegame.dat")) {
KGrMessage::information (view, i18n ("Save Game"),
i18n ("Please note: for reasons of simplicity, your saved game "
......@@ -1607,7 +1614,7 @@ void KGrGame::checkHighScore()
high2.close();
if (KGrGameIO::safeRename (high2.fileName(),
if (KGrGameIO::safeRename (view, high2.fileName(),
userDataDir + "hi_" + prefix + ".dat")) {
// Remove a redundant popup message.
// KGrMessage::information (view, i18n ("Save High Score"),
......
......@@ -350,7 +350,8 @@ KGrGameData * KGrGameIO::initGameData (Owner o)
return (g);
}
bool KGrGameIO::safeRename (const QString & oldName, const QString & newName)
bool KGrGameIO::safeRename (QWidget * theView, const QString & oldName,
const QString & newName)
{
QFile newFile (newName);
if (newFile.exists()) {
......@@ -359,17 +360,15 @@ bool KGrGameIO::safeRename (const QString & oldName, const QString & newName)
// upcoming QFile::rename will fail, according to Qt4 docs. This
// seems to be true with reiserfs at least.
if (! newFile.remove()) {
// TODO - Implement access to "view" and "i18n".
// KGrMessage::information (view, i18n ("Rename File"),
// i18n ("Cannot delete previous version of file '%1'.", newName));
KGrMessage::information (theView, i18n ("Rename File"),
i18n ("Cannot delete previous version of file '%1'.", newName));
return false;
}
}
QFile oldFile (oldName);
if (! oldFile.rename (newName)) {
// TODO - Implement access to "view" and "i18n".
// KGrMessage::information (view, i18n ("Rename File"),
// i18n ("Cannot rename file '%1' to '%2'.", oldName, newName));
KGrMessage::information (theView, i18n ("Rename File"),
i18n ("Cannot rename file '%1' to '%2'.", oldName, newName));
return false;
}
return true;
......
......@@ -90,7 +90,8 @@ public:
/*
* Rename a file, first removing any existing file that has the target name.
*/
static bool safeRename (const QString & oldName, const QString & newName);
static bool safeRename (QWidget * theView, const QString & oldName,
const QString & newName);
private:
QWidget * view;
......
......@@ -48,16 +48,6 @@ const char EDIT_TEST = '2';
const int FIELDWIDTH = 28;
const int FIELDHEIGHT = 20;
// TODO - Probably belongs in kgrrulebook.h. That is the only place it is used.
typedef struct {
int hwalk;
int hfall;
int ewalk;
int efall;
int ecaptive;
int hole;
} Timing;
const int DIGDELAY = 200;
const int STEP = 4;
......@@ -166,7 +156,6 @@ enum Setting {PLAY_SOUNDS, // Sound effects on/off.
const int ConcreteWall = 1;
// TODO - Should these be uchar?
typedef char DirectionFlag;
typedef char AccessFlag;
typedef char Flags;
......
......@@ -71,6 +71,8 @@ KGrLevelPlayer::~KGrLevelPlayer()
kDebug() << "LEVEL PLAYER BEING DELETED.";
playerCount--;
// TODO - Remove this debugging code.
if (recording) {
int ch = 0;
for (int i = 0; i <= (recIndex + 1); i ++) {
ch = (uchar)(recording->content.at(i));
......@@ -88,6 +90,7 @@ KGrLevelPlayer::~KGrLevelPlayer()
j++;
}
dbe1 "\n%d bytes\n", j);
}
// TODO - Do we need this delete?
// while (! enemies.isEmpty()) {
......@@ -98,6 +101,7 @@ KGrLevelPlayer::~KGrLevelPlayer()
void KGrLevelPlayer::init (KGrCanvas * view, const int mode,
KGrRecording * pRecording, const bool pPlayback)
{
// TODO - Remove?
playerCount++;
if (playerCount > 1) {
KMessageBox::information (view,
......@@ -130,7 +134,6 @@ void KGrLevelPlayer::init (KGrCanvas * view, const int mode,
rules = new KGrScavengerRules (this);
break;
}
// TODO - Remove. rules->printRules();
recIndex = 0;
recCount = 0;
......@@ -293,9 +296,6 @@ void KGrLevelPlayer::startDigging (Direction diggingDirection)
// The hero can dig as requested: the chosen brick is at (digI, digJ).
grid->changeCellAt (digI, digJ, HOLE);
// Delete the brick-image so that animations are visible in all themes.
// TODO - Remove. emit paintCell (digI, digJ, FREE, 0);
// Start the brick-opening animation (non-repeating).
int id = emit makeSprite (BRICK, digI, digJ);
emit startAnimation (id, false, digI, digJ,
......@@ -342,20 +342,16 @@ void KGrLevelPlayer::processDugBricks (const int scaledTime)
// << "time" << (t.elapsed() - dugBrick->startTime);
// Dispose of the dug brick and remove it from the list.
emit deleteSprite (dugBrick->id);
// TODO - Remove. emit paintCell (dugBrick->digI, dugBrick->digJ, BRICK);
delete dugBrick;
iterator.remove();
}
// TODO - Hero gets hidden by dug-brick in the Egyptian theme.
// TODO - Why do we get so many MISSED ticks when we dig?
// TODO - Implement speed-variation as a parameter of tick().
}
}
}
void KGrLevelPlayer::prepareToPlay()
{
// TODO - Should this be a signal?
kDebug() << "Set mouse to:" << targetI << targetJ;
emit setMousePos (targetI, targetJ);
playState = Ready;
......@@ -656,21 +652,22 @@ bool KGrLevelPlayer::heroCaught (const int heroX, const int heroY)
pointsPerCell_1 = enemy->whereAreYou (enemyX, enemyY) - 1;
if (((heroX < enemyX) ? ((heroX + pointsPerCell_1) >= enemyX) :
(heroX <= (enemyX + pointsPerCell_1))) &&
// TODO - Remove? ((heroY < enemyY) ?
// ((heroY + pointsPerCell_1) >= enemyY) :
((heroY < enemyY) ? ((heroY + pointsPerCell_1) > enemyY) :
(heroY <= (enemyY + pointsPerCell_1)))) {
dbk << "Caught by";
enemy->showState();
return true;
}
}
return false;
}
bool KGrLevelPlayer::standOnEnemy (const int spriteId, const int x, const int y)
KGrEnemy * KGrLevelPlayer::standOnEnemy (const int spriteId,
const int x, const int y)
{
int minEnemies = (spriteId == heroId) ? 1 : 2;
if (enemies.count() < minEnemies) {
return false;
return 0;
}
int enemyX, enemyY, pointsPerCell;
foreach (KGrEnemy * enemy, enemies) {
......@@ -679,10 +676,10 @@ bool KGrLevelPlayer::standOnEnemy (const int spriteId, const int x, const int y)
(enemyY == (y + pointsPerCell - 1))) &&
(enemyX > (x - pointsPerCell)) &&
(enemyX < (x + pointsPerCell))) {
return true;
return enemy;
}
}
return false;
return 0;
}
bool KGrLevelPlayer::bumpingFriend (const int spriteId, const Direction dirn,
......@@ -770,6 +767,9 @@ void KGrLevelPlayer::tick (bool missed, int scaledTime)
// We want to continue the demo if it is the startup demo.
// We also want to continue to next level after a demo level
// that signals endLevel (DEAD) or even endLevel (NORMAL).
// TODO - Playback case is handled in endLevel (DEAD) now, but we
// still could run out of recorded moves or get a KILL_HERO
// action, then what? Replay of KILL_HERO fails to finish.
dbk << "END_OF_RECORDING - or KILL_HERO ACTION.";
return; // End of recording.
}
......@@ -797,7 +797,6 @@ void KGrLevelPlayer::tick (bool missed, int scaledTime)
if ((status == WON_LEVEL) || (status == DEAD)) {
// TODO - Can this unsolicited timer pause cause problems in KGrGame?
timer->pause();
// TODO ? If caught in a brick, brick-closing animation is unfinished.
// Queued connection ensures KGrGame slot runs AFTER return from here.
emit endLevel (status);
kDebug() << "END OF LEVEL";
......
......@@ -223,9 +223,9 @@ public:
* @param x The X grid-position of the sprite (within a cell).
* @param y The Y grid-position of the sprite (within a cell).
*
* @return True if the hero or enemy is standing on an enemy.
* @return Pointer to the enemy the sprite is standing on - or 0.
*/
bool standOnEnemy (const int spriteId, const int x, const int y);
KGrEnemy * standOnEnemy (const int spriteId, const int x, const int y);
/**
* Helper function to determine whether an enemy is colliding with another
......
......@@ -91,8 +91,6 @@ Direction KGrTraditionalRules::findBestWay (const int eI, const int eJ,
return UP; // (e.g. brick above is closed):
} // but keep trying.
// TODO - Add !standOnEnemy() && as a condition here.
// TODO - And maybe !((*playfield)[x][y+1]->whatIam() == HOLE)) not just out of hole,
bool canStand = (grid->enemyMoves (eI, eJ) & dFlag [STAND]) ||
(grid->enemyOccupied (eI, eJ + 1) > 0);
if (! canStand) {
......@@ -368,16 +366,6 @@ int KGrTraditionalRules::distanceDown (int x, int y, int deltah)
}
}
if (rungs == 1) {
// TODO - Check for another enemy in this space, maybe in KGrRunner.
// TODO - Maybe the presence of another enemy below could be a bool
// TODO - parameter for findBestWay() ... NO, that won't work, we
// TODO - need to know if there is an enemy ANYWHERE under a LR path.
// QListIterator<KGrEnemy *> i (*enemies);
// while (i.hasNext()) {
// KGrEnemy * enemy = i.next();
// if ((x*16==enemy->getx()) && (y*16+16==enemy->gety()))
// rungs = 0; // Pit is blocked. Find another way.
// }
if (grid->enemyOccupied (x, y + 1) > 0) {
dbk2 << "Pit block =" << grid->enemyOccupied (x, y + 1)
<< "at" << x << (y + 1);
......@@ -427,9 +415,6 @@ int KGrTraditionalRules::canWalkLR (int direction, int x, int y)
bool KGrTraditionalRules::willNotFall (int x, int y)
{
// TODO - Remove ... int c, cmax;
// TODO - Remove ... KGrEnemy *enemy;
// Check the ceiling.
switch (grid->cellType (x, y)) {
case LADDER:
......@@ -443,32 +428,20 @@ bool KGrTraditionalRules::willNotFall (int x, int y)
switch (grid->cellType (x, y + 1)) {
// Cases where the enemy knows he will fall.
case FREE:
case HLADDER:
case FBRICK:
// N.B. The enemy THINKS he can run over a NUGGET, a buried BAR or a HOLE.
// The last of these cases allows the hero to trap the enemy, of course.
// Note that there are several Traditional levels that require an enemy to
// be trapped permanently in a pit containing a nugget, as he runs towards
// you. It is also possible to use a buried BAR in the same way.
// TODO - Check for another enemy down below, maybe in KGrRunner.
// TODO - Maybe the presence of another enemy below could be a bool
// TODO - parameter for findBestWay() ... NO, that won't work, we
// TODO - need to know if there is an enemy ANYWHERE under a LR path.
case FREE:
case HLADDER:
case FBRICK:
if (grid->enemyOccupied (x, y + 1) > 0) {
dbk2 << "Occupied =" << grid->enemyOccupied (x, y + 1)
<< "at" << x << (y + 1);
return true;
}
// cmax = enemies->count();
// for (c = 0; c < cmax; c++) {
// enemy = enemies->at (c);
// if ((enemy->getx()==16*x) && (enemy->gety()==16*(y+1)))
// return true; // Standing on a friend.
// }
return false; // Will fall: there is no floor.
break;
......@@ -514,8 +487,6 @@ Direction KGrKGoldrunnerRules::findBestWay (const int eI, const int eJ,
return UP; // (e.g. brick above is closed):
} // but keep trying.
// TODO - Add !standOnEnemy() && as a condition here.
// TODO - And maybe !((*playfield)[x][y+1]->whatIam() == HOLE)) not just out of hole,
bool canStand = (grid->enemyMoves (eI, eJ) & dFlag [STAND]) ||
(grid->enemyOccupied (eI, eJ + 1) > 0);
if (! canStand) {
......@@ -549,6 +520,11 @@ Direction KGrKGoldrunnerRules::findWayUp (const int eI, const int eJ)
{
int i, k;
i = k = eI;
// Must be able to stand AND move through cells when looking left or right.
Flags leftOK = (dFlag [LEFT] | dFlag [STAND]);
Flags rightOK = (dFlag [RIGHT] | dFlag [STAND]);
if (grid->enemyMoves (eI, eJ) & dFlag [UP]) {
return UP; // Go up from current position.
}
......@@ -558,7 +534,7 @@ Direction KGrKGoldrunnerRules::findWayUp (const int eI, const int eJ)
if (grid->enemyMoves (i, eJ) & dFlag [UP]) {
return LEFT; // Go left, then up later.
}
else if (! (grid->enemyMoves (i--, eJ) & dFlag [LEFT])) {
else if ((grid->enemyMoves (i--, eJ) & leftOK) != leftOK) {
i = -1;
}
}
......@@ -566,24 +542,21 @@ Direction KGrKGoldrunnerRules::findWayUp (const int eI, const int eJ)
if (grid->enemyMoves (k, eJ) & dFlag [UP]) {
return RIGHT; // Go right, then up later.
}
else if (!(grid->enemyMoves (k++, eJ) & dFlag [RIGHT])) {
else if ((grid->enemyMoves (k++, eJ) & rightOK) != rightOK) {
k = FIELDWIDTH + 1;
}
}
}
}
// BUG FIX - Ian W., 30/4/01 - Don't leave an enemy standing in mid air.
if (false) // TODO - Was supposed to be canStand() - maybe redundant now -
// canStand() returned (firmGround || standOnEnemy()).
return DOWN;
else
return STAND;
return STAND;
}
Direction KGrKGoldrunnerRules::findWayDown (const int eI, const int eJ)
{
int i, k;
i = k = eI;
// In this search, no need to test for STAND. Fall and ladder are both OK.
if (grid->enemyMoves (eI, eJ) & dFlag [DOWN]) {
return DOWN; // Go down from current position.
}
......@@ -614,13 +587,17 @@ Direction KGrKGoldrunnerRules::findWayLeft (const int eI, const int eJ)
{
int i, k;
i = k = eJ;
if (grid->enemyMoves (eI, eJ) & dFlag [LEFT]) {
// Must be able to stand and move through cells when checking move-left.
Flags leftOK = (dFlag [LEFT] | dFlag [STAND]);
if ((grid->enemyMoves (eI, eJ) & leftOK) == leftOK) {
return LEFT; // Go left from current position.
}
else {
while ((i >= 0) || (k <= FIELDHEIGHT)) {
if (i >= 0) {
if (grid->enemyMoves (eI, i) & dFlag [LEFT]) {
if ((grid->enemyMoves (eI, i) & leftOK) == leftOK) {
return UP; // Go up, then left later.
}