File indexing completed on 2024-04-21 04:02:23

0001 /*
0002     SPDX-FileCopyrightText: 2009 Ian Wadham <iandw.au@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "kgrlevelgrid.h"
0008 #include "kgrrulebook.h"
0009 #include "kgrdebug.h"
0010 
0011 KGrRuleBook::KGrRuleBook (QObject * parent)
0012     :
0013     QObject              (parent),
0014     mVariableTiming      (true),
0015     mAlwaysCollectNugget (true),
0016     mRunThruHole         (true),
0017     mReappearAtTop       (true),
0018     mReappearRow         (2),
0019     mPointsPerCell       (4),
0020     mTurnAnywhere        (false)
0021 {
0022 }
0023 
0024 KGrRuleBook::~KGrRuleBook()
0025 {
0026 }
0027 
0028 void KGrRuleBook::setTiming (const int enemyCount)
0029 {
0030     Timing varTiming[6] = {
0031                           {40, 58, 78, 88, 340, 23},      // No enemies.
0032                           {50, 68, 78, 88, 340, 32},      // 1 enemy.
0033                           {57, 67, 114, 128, 540, 37},    // 2 enemies.
0034                           {60, 70, 134, 136, 660, 40},    // 3 enemies.
0035                           {63, 76, 165, 150, 800, 46},    // 4 enemies.
0036                           {70, 80, 189, 165, 920, 51}     // >4 enemies.
0037                           };
0038     if (mVariableTiming) {
0039         int choice = std::clamp(enemyCount, 0, 5);
0040         times  = varTiming [choice];
0041     }
0042 }
0043 
0044 
0045 // Initialise the flags for the rules.
0046 
0047 KGrTraditionalRules::KGrTraditionalRules (QObject * parent)
0048     :
0049     KGrRuleBook (parent)
0050 {
0051     mRules               = TraditionalRules;
0052 
0053     mVariableTiming      = true;    ///< More enemies imply less speed.
0054     mAlwaysCollectNugget = true;    ///< Enemies always collect nuggets.
0055     mRunThruHole         = true;    ///< Enemy can run L/R through dug hole.
0056     mReappearAtTop       = true;    ///< Enemies reborn at top of screen.
0057     mReappearRow         = 2;       ///< Row where enemies reappear.
0058     mPointsPerCell       = 4;       ///< Number of points in each grid-cell.
0059     mTurnAnywhere        = false;   ///< Change direction only at next cell.
0060     mEnemiesShowGold     = true;    ///< Show enemies carrying gold.
0061 
0062     Timing t = {40, 58, 78, 88, 340, 23};
0063     times = t;
0064 }
0065 
0066 KGrTraditionalRules::~KGrTraditionalRules()
0067 {
0068 }
0069 
0070 Direction KGrTraditionalRules::findBestWay (const int eI, const int eJ,
0071                                             const int hI, const int hJ,
0072                                             KGrLevelGrid * pGrid,
0073                                             bool /* leftRightSearch unused */)
0074 {
0075     grid = pGrid;
0076     if (grid->cellType (eI, eJ) == USEDHOLE) {  // Could not get out of hole
0077         return UP;              // (e.g. brick above is closed):
0078     }                       // but keep trying.
0079 
0080     bool canStand = (grid->enemyMoves (eI, eJ) & dFlag [STAND]) ||
0081                     (grid->enemyOccupied (eI, eJ + 1) > 0);
0082     if (! canStand) {
0083         dbk2 << "can stand" << (grid->enemyMoves (eI, eJ) & dFlag [STAND])
0084                  << "occ-below" << grid->enemyOccupied (eI, eJ + 1);
0085         return DOWN;
0086     }
0087     dbk2 << "not DOWN yet";
0088 
0089     // Traditional search strategy.
0090     Direction dirn = STAND;
0091     if (eJ == hJ) {
0092         dirn = getHero (eI, eJ, hI);        // Hero on same row.
0093         if (dirn != STAND) {
0094             return dirn;            // Can go towards him.
0095         }
0096     }
0097 
0098     if (eJ >= hJ) {             // Hero above or on same row.
0099         dirn = searchUp (eI, eJ, hJ);       // Find a way that leads up.
0100     }
0101     else {                  // Hero below enemy.
0102         dirn = searchDown (eI, eJ, hJ);     // Find way that leads down.
0103         dbk2 << "searchDown1" << eI << eJ << hJ << "ret" << dirn;
0104         if (dirn == STAND) {
0105             dirn = searchUp (eI, eJ, hJ);   // No go: try going up first.
0106         }
0107     }
0108 
0109     if (dirn == STAND) {            // When all else fails, look for
0110         dirn = searchDown (eI, eJ, eJ - 1); // a way below the hero.
0111         dbk2 << "searchDown2" << eI << eJ << (eJ - 1) << "ret" << dirn;
0112     }
0113 
0114     return dirn;
0115 }
0116 
0117 Direction KGrTraditionalRules::searchUp (int ew, int eh, int hh)
0118 {
0119     int i, ilen, ipos, j, jlen, jpos, deltah, rungs;
0120 
0121     deltah = eh - hh;           // Get distance up to hero's level.
0122 
0123     // Search for the best ladder right here or on the left.
0124     i = ew; ilen = 0; ipos = -1;
0125     while (i >= 1) {
0126         rungs = distanceUp (i, eh, deltah);
0127         if (rungs > ilen) {
0128             ilen = rungs;       // This the best yet.
0129             ipos = i;
0130         }
0131         if (searchOK (-1, i, eh))
0132             i--;            // Look further to the left.
0133         else
0134             i = -1;         // Cannot go any further to the left.
0135     }
0136 
0137     // Search for the best ladder on the right.
0138     j = ew; jlen = 0; jpos = -1;
0139     while (j < FIELDWIDTH) {
0140         if (searchOK (+1, j, eh)) {
0141             j++;            // Look further to the right.
0142             rungs = distanceUp (j, eh, deltah);
0143             if (rungs > jlen) {
0144                 jlen = rungs;       // This the best yet.
0145                 jpos = j;
0146             }
0147         }
0148         else
0149             j = FIELDWIDTH+1;       // Cannot go any further to the right.
0150     }
0151 
0152     if ((ilen == 0) && (jlen == 0)) // No ladder found.
0153         return STAND;
0154 
0155     // Choose a ladder to go to.
0156     if (ilen != jlen) {         // If the ladders are not the same
0157                                         // length, choose the longer one.
0158         if (ilen > jlen) {
0159             if (ipos == ew)     // If already on the best ladder, go up.
0160                 return UP;
0161             else
0162                 return LEFT;
0163         }
0164         else
0165             return RIGHT;
0166     }
0167     else {              // Both ladders are the same length.
0168 
0169         if (ipos == ew)         // If already on the best ladder, go up.
0170             return UP;
0171         else if (ilen == deltah) {  // If both reach the hero's level,
0172             if ((ew - ipos) <= (jpos - ew)) // choose the closest.
0173                 return LEFT;
0174             else
0175                 return RIGHT;
0176         }
0177         else return LEFT;       // Else choose the left ladder.
0178     }
0179 }
0180 
0181 Direction KGrTraditionalRules::searchDown (int ew, int eh, int hh)
0182 {
0183     int i, ilen, ipos, j, jlen, jpos, deltah, rungs, path;
0184 
0185     deltah = hh - eh;           // Get distance down to hero's level.
0186 
0187     // Search for the best way down, right here or on the left.
0188     ilen = 0; ipos = -1;
0189     i = (willNotFall (ew, eh)) ? ew : -1;
0190     rungs = distanceDown (ew, eh, deltah);
0191     if (rungs > 0) {
0192         ilen = rungs; ipos = ew;
0193     }
0194 
0195     while (i >= 1) {
0196         rungs = distanceDown (i - 1, eh, deltah);
0197         if (((rungs > 0) && (ilen == 0)) ||
0198             ((deltah > 0) && (rungs > ilen)) ||
0199             ((deltah <= 0) && (rungs < ilen) && (rungs != 0))) {
0200             ilen = rungs;       // This the best way yet.
0201             ipos = i - 1;
0202         }
0203         if (searchOK (-1, i, eh))
0204             i--;            // Look further to the left.
0205         else
0206             i = -1;         // Cannot go any further to the left.
0207     }
0208 
0209     // Search for the best way down, on the right.
0210     j = ew; jlen = 0; jpos = -1;
0211     while (j < FIELDWIDTH) {
0212         rungs = distanceDown (j + 1, eh, deltah);
0213         if (((rungs > 0) && (jlen == 0)) ||
0214             ((deltah > 0) && (rungs > jlen)) ||
0215             ((deltah <= 0) && (rungs < jlen) && (rungs != 0))) {
0216             jlen = rungs;       // This the best way yet.
0217             jpos = j + 1;
0218         }
0219         if (searchOK (+1, j, eh)) {
0220             j++;            // Look further to the right.
0221         }
0222         else
0223             j = FIELDWIDTH+1;       // Cannot go any further to the right.
0224     }
0225 
0226     if ((ilen == 0) && (jlen == 0)) // Found no way down.
0227         return STAND;
0228 
0229     // Choose a way down to follow.
0230     if (ilen == 0)
0231         path = jpos;
0232     else if (jlen == 0)
0233         path = ipos;
0234     else if (ilen != jlen) {        // If the ways down are not same length,
0235                                         // choose closest to hero's level.
0236         if (deltah > 0) {
0237             if (jlen > ilen)
0238                 path = jpos;
0239             else
0240                 path = ipos;
0241         }
0242         else {
0243             if (jlen > ilen)
0244                 path = ipos;
0245             else
0246                 path = jpos;
0247         }
0248     }
0249     else {              // Both ways down are the same length.
0250         if ((deltah > 0) &&     // If both reach the hero's level,
0251             (ilen == deltah)) {     // choose the closest.
0252             if ((ew - ipos) <= (jpos - ew))
0253                 path = ipos;
0254             else
0255                 path = jpos;
0256         }
0257         else
0258             path = ipos;        // Else, go left or down.
0259     }
0260 
0261     if (path == ew)
0262         return DOWN;
0263     else if (path < ew)
0264         return LEFT;
0265     else
0266         return RIGHT;
0267 }
0268 
0269 Direction KGrTraditionalRules::getHero (int eI, int eJ, int hI)
0270 {
0271     int i, inc, returnValue;
0272 
0273     inc = (eI > hI) ? -1 : +1;
0274     i = eI;
0275     while (i != hI) {
0276         returnValue = canWalkLR (inc, i, eJ);
0277         if (returnValue > 0)
0278             i = i + inc;        // Can run further towards the hero.
0279         else if (returnValue < 0)
0280             break;          // Will run into a wall regardless.
0281         else
0282             return STAND;       // Won't run over a hole.
0283     }
0284 
0285     if (i < eI)     return LEFT;
0286     else if (i > eI)    return RIGHT;
0287     else        return STAND;
0288 }
0289 
0290 int KGrTraditionalRules::distanceUp (int x, int y, int deltah)
0291 {
0292     int rungs = 0;
0293 
0294     // If there is a ladder at (x,y), return its length, else return zero.
0295     while (grid->cellType (x, y - rungs) == LADDER) {
0296         rungs++;
0297         if (rungs >= deltah) {      // To hero's level is enough.
0298             break;
0299         }
0300     }
0301     return rungs;
0302 }
0303 
0304 int KGrTraditionalRules::distanceDown (int x, int y, int deltah)
0305 {
0306     // When deltah > 0, we want an exit sideways at the hero's level or above.
0307     // When deltah <= 0, we can go down any distance (as a last resort).
0308 
0309     int rungs = -1;
0310     int exitRung = 0;
0311     bool canGoThru = true;
0312     char objType;
0313 
0314     // If there is a way down at (x,y), return its length, else return zero.
0315     // Because rungs == -1, we first check that level y is not blocked here.
0316     while (canGoThru) {
0317         objType = grid->cellType (x, y + rungs + 1);
0318         switch (objType) {
0319         case BRICK:
0320         case CONCRETE:
0321         case HOLE:          // Enemy cannot go DOWN through a hole.
0322         case USEDHOLE:
0323             if ((deltah > 0) && (rungs <= deltah))
0324                 exitRung = rungs;
0325             if ((objType == HOLE) && (rungs < 0))
0326                 rungs = 0;      // Enemy can go SIDEWAYS through a hole.
0327             else
0328                 canGoThru = false;  // Cannot go through here.
0329             break;
0330         case LADDER:
0331         case BAR:           // Can go through or stop.
0332             rungs++;            // Add to path length.
0333             if ((deltah > 0) && (rungs >= 0)) {
0334                 // If at or above hero's level, check for an exit from ladder.
0335                 if ((rungs - 1) <= deltah) {
0336                     // Maybe can stand on top of ladder and exit L or R.
0337                     if ((objType == LADDER) && (searchOK (-1, x, y+rungs-1) ||
0338                                                 searchOK (+1, x, y+rungs-1)))
0339                         exitRung = rungs - 1;
0340                     // Maybe can exit L or R from ladder body or pole.
0341                     if ((rungs <= deltah) && (searchOK (-1, x, y+rungs) ||
0342                                               searchOK (+1, x, y+rungs)))
0343                         exitRung = rungs;
0344                 }
0345                 else
0346                     canGoThru = false;  // Should stop at hero's level.
0347             }
0348             break;
0349         default:
0350             rungs++;            // Can go through.  Add to path length.
0351             break;
0352         }
0353     }
0354     if (rungs == 1) {
0355         if (grid->enemyOccupied (x, y + 1) > 0) {
0356             dbk2 << "Pit block =" << grid->enemyOccupied (x, y + 1)
0357                      << "at" << x << (y + 1);
0358             rungs = 0;      // Pit is blocked.  Find another way.
0359         }
0360     }
0361     if (rungs <= 0)
0362         return 0;           // There is no way down.
0363     else if (deltah > 0)
0364         return exitRung;        // We want to take an exit, if any.
0365     else
0366         return rungs;           // We can go down all the way.
0367 }
0368 
0369 bool KGrTraditionalRules::searchOK (int direction, int x, int y)
0370 {
0371     // Check whether it is OK to search left or right.
0372     if (canWalkLR (direction, x, y) > 0) {
0373         // Can go into that cell, but check for a fall.
0374         if (willNotFall (x+direction, y))
0375             return true;
0376     }
0377     return false;           // Cannot go into and through that cell.
0378 }
0379 
0380 int KGrTraditionalRules::canWalkLR (int direction, int x, int y)
0381 {
0382     if (willNotFall (x, y)) {
0383         switch (grid->cellType (x+direction, y)) {
0384         case CONCRETE:
0385         case BRICK:
0386         case USEDHOLE:
0387             return -1;      // Will be halted in current cell.
0388             break;
0389         default:
0390             // NB. FREE, LADDER, HLADDER, NUGGET and BAR are OK of course,
0391             //     but enemies can also walk left/right through a HOLE and
0392             //     THINK they can walk left/right through a FBRICK.
0393 
0394             return +1;      // Can walk into next cell.
0395             break;
0396         }
0397     }
0398     else
0399         return 0;           // Will fall before getting there.
0400 }
0401 
0402 bool KGrTraditionalRules::willNotFall (int x, int y)
0403 {
0404     // Check the ceiling.
0405     switch (grid->cellType (x, y)) {
0406     case LADDER:
0407     case BAR:
0408         return true; break;     // OK, can hang on ladder or pole.
0409     default:
0410         break;
0411     }
0412 
0413     // Check the floor.
0414     switch (grid->cellType (x, y + 1)) {
0415 
0416     // Cases where the enemy knows he will fall.
0417     // N.B. The enemy THINKS he can run over a NUGGET, a buried BAR or a HOLE.
0418     // The last of these cases allows the hero to trap the enemy, of course.
0419 
0420     // Note that there are several Traditional levels that require an enemy to
0421     // be trapped permanently in a pit containing a nugget, as he runs towards
0422     // you.  It is also possible to use a buried BAR in the same way.
0423     case FREE:
0424     case HLADDER:
0425     case FBRICK:
0426         if (grid->enemyOccupied (x, y + 1) > 0) {
0427             dbk2 << "Occupied =" << grid->enemyOccupied (x, y + 1)
0428                      << "at" << x << (y + 1);
0429             return true;
0430         }
0431         return false;           // Will fall: there is no floor.
0432         break;
0433 
0434     default:
0435         return true;            // OK, will not fall.
0436         break;
0437     }
0438 }
0439 
0440 
0441 KGrKGoldrunnerRules::KGrKGoldrunnerRules (QObject * parent)
0442     :
0443     KGrRuleBook     (parent)
0444 {
0445     mRules               = KGoldrunnerRules;
0446 
0447     mVariableTiming      = false;   ///< Speed same for any no. of enemies.
0448     mAlwaysCollectNugget = false;   ///< Enemies sometimes collect nuggets.
0449     mRunThruHole         = false;   ///< Enemy cannot run through dug hole.
0450     mReappearAtTop       = false;   ///< Enemies reborn at start position.
0451     mReappearRow         = -1;      ///< Row where enemies reappear (N/A).
0452     mPointsPerCell       = 4;       ///< Number of points in each grid-cell.
0453     mTurnAnywhere        = false;   ///< Change direction only at next cell.
0454     mEnemiesShowGold     = true;    ///< Show enemies carrying gold.
0455 
0456     Timing t = {45, 50, 55, 100, 1000, 40};
0457     times = t;
0458 }
0459 
0460 KGrKGoldrunnerRules::~KGrKGoldrunnerRules()
0461 {
0462 }
0463 
0464 Direction KGrKGoldrunnerRules::findBestWay (const int eI, const int eJ,
0465                                             const int hI, const int hJ,
0466                                             KGrLevelGrid * pGrid,
0467                                             bool leftRightSearch)
0468 {
0469     dbk2 << eI << eJ << hI << hJ;
0470     grid = pGrid;
0471 
0472     if (grid->cellType (eI, eJ) == USEDHOLE) {  // Could not get out of hole
0473         return UP;              // (e.g. brick above is closed):
0474     }                       // but keep trying.
0475 
0476     bool canStand = (grid->enemyMoves (eI, eJ) & dFlag [STAND]) ||
0477                     (grid->enemyOccupied (eI, eJ + 1) > 0);
0478     if (! canStand) {
0479         dbk2 << "can stand" << (grid->enemyMoves (eI, eJ) & dFlag [STAND])
0480                  << "occ-below" << grid->enemyOccupied (eI, eJ + 1);
0481         return DOWN;
0482     }
0483 
0484     // KGoldrunner search strategy.
0485     if (leftRightSearch) {
0486         if (eI > hI) {
0487             return findWayLeft  (eI, eJ);
0488         }
0489         if (eI < hI) {
0490             return findWayRight (eI, eJ);
0491         }
0492     }
0493     else {
0494         if (eJ > hJ) {
0495             return findWayUp    (eI, eJ);
0496         }
0497         if (eJ < hJ) {
0498             return findWayDown  (eI, eJ);
0499         }
0500     }
0501 
0502     return STAND;
0503 }
0504 
0505 Direction KGrKGoldrunnerRules::findWayUp (const int eI, const int eJ)
0506 {
0507     int i, k;
0508     i = k = eI;
0509 
0510     // Must be able to stand AND move through cells when looking left or right.
0511     Flags leftOK  = (dFlag [LEFT] | dFlag [STAND]);
0512     Flags rightOK = (dFlag [RIGHT] | dFlag [STAND]);
0513 
0514     if (grid->enemyMoves (eI, eJ) & dFlag [UP]) {
0515         return UP;          // Go up from current position.
0516     }
0517     else {
0518         while ((i >= 0) || (k <= FIELDWIDTH)) {
0519             if (i >= 0) {
0520                 if (grid->enemyMoves (i, eJ) & dFlag [UP]) {
0521                     return LEFT;    // Go left, then up later.
0522                 }
0523                 else if ((grid->enemyMoves (i--, eJ) & leftOK) != leftOK) {
0524                     i = -1;
0525                 }
0526             }
0527             if (k <= FIELDWIDTH) {
0528                 if (grid->enemyMoves (k, eJ) & dFlag [UP]) {
0529                     return RIGHT;   // Go right, then up later.
0530                 }
0531                 else if ((grid->enemyMoves (k++, eJ) & rightOK) != rightOK) {
0532                     k = FIELDWIDTH + 1;
0533                 }
0534             }
0535         }
0536     }
0537     return STAND;
0538 }
0539 
0540 Direction KGrKGoldrunnerRules::findWayDown (const int eI, const int eJ)
0541 {
0542     int i, k;
0543     i = k = eI;
0544 
0545     // In this search, no need to test for STAND.  Fall and ladder are both OK.
0546     if (grid->enemyMoves (eI, eJ) & dFlag [DOWN]) {
0547         return DOWN;            // Go down from current position.
0548     }
0549     else {
0550         while ((i >= 0) || (k <= FIELDWIDTH)) {
0551             if (i >= 0) {
0552                 if (grid->enemyMoves (i, eJ) & dFlag [DOWN]) {
0553                     return LEFT;    // Go left, then down later.
0554                 }
0555                 else if (! (grid->enemyMoves (i--, eJ) & dFlag [LEFT])) {
0556                     i = -1;
0557                 }
0558             }
0559             if (k <= FIELDWIDTH) {
0560                 if (grid->enemyMoves (k, eJ) & dFlag [DOWN]) {
0561                     return RIGHT;   // Go right, then down later.
0562                 }
0563                 else if (! (grid->enemyMoves (k++, eJ) & dFlag [RIGHT])) {
0564                     k = FIELDWIDTH + 1;
0565                 }
0566             }
0567         }
0568     }
0569     return STAND;           // Cannot go down.
0570 }
0571 
0572 Direction KGrKGoldrunnerRules::findWayLeft (const int eI, const int eJ)
0573 {
0574     int i, k;
0575     i = k = eJ;
0576 
0577     // Must be able to stand and move through cells when checking move-left.
0578     Flags leftOK = (dFlag [LEFT] | dFlag [STAND]);
0579 
0580     if ((grid->enemyMoves (eI, eJ) & leftOK) == leftOK) {
0581         return LEFT;            // Go left from current position.
0582     }
0583     else {
0584         while ((i >= 0) || (k <= FIELDHEIGHT)) {
0585             if (i >= 0) {
0586                 if ((grid->enemyMoves (eI, i) & leftOK) == leftOK) {
0587                     return UP;      // Go up, then left later.
0588                 }
0589                 else if (! (grid->enemyMoves (eI, i--) & dFlag [UP])) {
0590                     i = -1;
0591                 }
0592             }
0593             if (k <= FIELDHEIGHT) {
0594                 if ((grid->enemyMoves (eI, k) & leftOK) == leftOK) {
0595                     return DOWN;    // Go down, then left later.
0596                 }
0597                 else if (! (grid->enemyMoves (eI, k++) & dFlag [DOWN])) {
0598                     k = FIELDHEIGHT + 1;
0599                 }
0600             }
0601         }
0602     }
0603     return STAND;           // Cannot go left.
0604 }
0605 
0606 Direction KGrKGoldrunnerRules::findWayRight (const int eI, const int eJ)
0607 {
0608     int i, k;
0609     i = k = eJ;
0610 
0611     // Must be able to stand and move through cells when checking move-right.
0612     Flags rightOK = (dFlag [RIGHT] | dFlag [STAND]);
0613 
0614     if ((grid->enemyMoves (eI, eJ) & rightOK) == rightOK) {
0615         return RIGHT;           // Go right from current position.
0616     }
0617     else {
0618         while ((i >= 0) || (k <= FIELDHEIGHT)) {
0619             if (i >= 0) {
0620                 if ((grid->enemyMoves (eI, i) & rightOK) == rightOK) {
0621                     return UP;      // Go up, then right later.
0622                 }
0623                 else if (!(grid->enemyMoves (eI, i--) & dFlag [UP])) {
0624                     i = -1;
0625                 }
0626             }
0627             if (k <= FIELDHEIGHT) {
0628                 if ((grid->enemyMoves (eI, k) & rightOK) == rightOK) {
0629                     return DOWN;    // Go down, then right later.
0630                 }
0631                 else if (! (grid->enemyMoves (eI, k++) & dFlag [DOWN])) {
0632                     k = FIELDHEIGHT + 1;
0633                 }
0634             }
0635         }
0636     }
0637     return STAND;           // Cannot go right.
0638 }
0639 
0640 
0641 KGrScavengerRules::KGrScavengerRules (QObject * parent)
0642     :
0643     KGrRuleBook (parent)
0644 {
0645     mRules               = ScavengerRules;
0646 
0647     mVariableTiming      = false;   ///< Speed same for any no. of enemies.
0648     mAlwaysCollectNugget = true;    ///< Enemies always collect nuggets.
0649     mRunThruHole         = true;    ///< Enemy can run L/R through dug hole.
0650     mReappearAtTop       = true;    ///< Enemies reborn at top of screen.
0651     mReappearRow         = 1;       ///< Row where enemies reappear.
0652     mPointsPerCell       = 12;      ///< Number of points in each grid-cell.
0653     mTurnAnywhere        = true;    ///< Change direction anywhere in cell.
0654     mEnemiesShowGold     = false;   ///< Conceal enemies carrying gold.
0655 
0656     Timing t = {45, 50, 55, 100, 1000, 40};
0657     times = t;
0658 }
0659 
0660 KGrScavengerRules::~KGrScavengerRules()
0661 {
0662 }
0663 
0664 Direction KGrScavengerRules::findBestWay   (const int eI, const int eJ,
0665                                             const int hI, const int hJ,
0666                                             KGrLevelGrid * pGrid,
0667                                             bool /* leftRightSearch unused */)
0668 {
0669     dbk2 << eI << eJ << hI << hJ;
0670     grid = pGrid;
0671     return RIGHT;
0672 }
0673 
0674 #include "moc_kgrrulebook.cpp"