• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdegames API Reference
  • KDE Home
  • Contact Us
 

kgoldrunner

  • sources
  • kde-4.14
  • kdegames
  • kgoldrunner
  • src
kgrlevelplayer.cpp
Go to the documentation of this file.
1 #include "kgrdebug.h"
2 
3 /****************************************************************************
4  * Copyright 2009 Ian Wadham <iandw.au@gmail.com> *
5  * *
6  * This program is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU General Public License as *
8  * published by the Free Software Foundation; either version 2 of *
9  * the License, or (at your option) any later version. *
10  * *
11  * This program is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License *
17  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18  ****************************************************************************/
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 
23 // Include kgrgame.h only to access flags KGrGame::bugFix and KGrGame::logging.
24 #include "kgrgame.h"
25 #include "kgrscene.h"
26 
27 #include "kgrtimer.h"
28 #include "kgrview.h"
29 #include "kgrlevelplayer.h"
30 #include "kgrrulebook.h"
31 #include "kgrlevelgrid.h"
32 #include "kgrrunner.h"
33 
34 #include <KDebug>
35 #include <KMessageBox> // TODO - Remove.
36 #include <KRandomSequence>
37 
38 KGrLevelPlayer::KGrLevelPlayer (QObject * parent, KRandomSequence * pRandomGen)
39  :
40  QObject (parent),
41  game (parent),
42  randomGen (pRandomGen),
43  hero (0),
44  controlMode (MOUSE),
45  holdKeyOption (CLICK_KEY),
46  nuggets (0),
47  playState (NotReady),
48  recording (0),
49  playback (false),
50  targetI (1),
51  targetJ (1),
52  direction (NO_DIRECTION),
53  newDirection (NO_DIRECTION),
54  timer (0),
55  digCycleTime (200), // Milliseconds per dig-timing cycle (default).
56  digCycleCount (40), // Cycles while hole is fully open (default).
57  digOpeningCycles (5), // Cycles for brick-opening animation.
58  digClosingCycles (4), // Cycles for brick-closing animation.
59  digKillingTime (2), // Cycle at which enemy/hero gets killed.
60  dX (0), // X motion for KEYBOARD + HOLD_KEY option.
61  dY (0) // Y motion for KEYBOARD + HOLD_KEY option.
62 {
63  t.start(); // IDW
64 
65  dbgLevel = 0;
66 }
67 
68 int KGrLevelPlayer::playerCount = 0;
69 
70 KGrLevelPlayer::~KGrLevelPlayer()
71 {
72  qDeleteAll(dugBricks);
73  dugBricks.clear(); //TODO: necessary?
74  kDebug() << "LEVEL PLAYER BEING DELETED.";
75  playerCount--;
76 
77 // TODO - Remove this debugging code.
78 if (recording) {
79  int ch = 0;
80  for (int i = 0; i <= (recIndex + 1); i ++) {
81  ch = (uchar)(recording->content.at(i));
82  dbe1 "%03d ", ch);
83  if (ch == 0)
84  break;
85  }
86  dbe1 "\n%d bytes\n", recIndex + 1);
87  int j = 0;
88  while (j < recording->draws.size()) {
89  ch = (uchar)(recording->draws.at(j));
90  dbe1 "%03d ", ch);
91  if (ch == 0)
92  break;
93  j++;
94  }
95  dbe1 "\n%d bytes\n", j);
96 }
97 
98 }
99 
100 void KGrLevelPlayer::init (KGrView * view,
101  KGrRecording * pRecording,
102  const bool pPlayback,
103  const bool gameFrozen)
104 {
105  // TODO - Remove?
106  playerCount++;
107  if (playerCount > 1) {
108  KMessageBox::information (view,
109  QString("ERROR: KGrLevelPlayer Count = %1").arg(playerCount),
110  "KGrLevelPlayer");
111  }
112 
113  recording = pRecording;
114  playback = pPlayback;
115 
116  // Create the internal model of the level-layout.
117  grid = new KGrLevelGrid (this, recording);
118 
119  // Set mouse/keyboard/laptop control and click/hold option for keyboard.
120  controlMode = recording->controlMode;
121  holdKeyOption = recording->keyOption;
122 
123  dX = 0; // X motion for KEYBOARD + HOLD_KEY.
124  dY = 0; // Y motion for KEYBOARD + HOLD_KEY.
125  levelWidth = recording->width;
126  levelHeight = recording->height;
127 
128  reappearIndex = levelWidth; // Initialise the enemy-rebirth code.
129  reappearPos.fill (1, levelWidth);
130 
131  // Set the rules of this game.
132  switch (recording->rules) {
133  case TraditionalRules:
134  rules = new KGrTraditionalRules (this);
135  break;
136  case KGoldrunnerRules:
137  rules = new KGrKGoldrunnerRules (this);
138  break;
139  case ScavengerRules:
140  rules = new KGrScavengerRules (this);
141  break;
142  }
143 
144  recIndex = 0;
145  recCount = 0;
146  randIndex = 0;
147  T = 0;
148 
149  view->gameScene()->setGoldEnemiesRule (rules->enemiesShowGold());
150 
151  // Determine the access for hero and enemies to and from each grid-cell.
152  grid->calculateAccess (rules->runThruHole());
153 
154  // Connect to code that paints grid cells and start-positions of sprites.
155  connect (this, SIGNAL (paintCell(int,int,char)),
156  view->gameScene(), SLOT (paintCell(int,int,char)));
157 
158  connect (this, SIGNAL (makeSprite(char,int,int)),
159  view->gameScene(), SLOT (makeSprite(char,int,int)));
160 
161  // Connect to the mouse-positioning code in the graphics.
162  connect (this, SIGNAL (getMousePos(int&,int&)),
163  view->gameScene(), SLOT (getMousePos(int&,int&)));
164 
165  connect (this, SIGNAL (setMousePos(int,int)),
166  view->gameScene(), SLOT (setMousePos(int,int)));
167 
168  // Show the layout of this level in the view (KGrCanvas).
169  int wall = ConcreteWall;
170  int enemyCount = 0;
171  for (int j = wall ; j < levelHeight + wall; j++) {
172  for (int i = wall; i < levelWidth + wall; i++) {
173  char type = grid->cellType (i, j);
174 
175  // Hide false bricks.
176  if (type == FBRICK) {
177  type = BRICK;
178  }
179 
180  // Count the gold in this level.
181  if (type == NUGGET) {
182  nuggets++;
183  }
184 
185  // If the hero is here, leave the tile empty.
186  if (type == HERO) {
187  emit paintCell (i, j, FREE);
188  }
189 
190  // If an enemy is here, count him and leave the tile empty.
191  else if (type == ENEMY) {
192  enemyCount++;
193  emit paintCell (i, j, FREE);
194  }
195 
196  // Or, just paint this tile.
197  else {
198  emit paintCell (i, j, type);
199  }
200  }
201  }
202 
203  // Set the timing rules, maybe based on the number of enemies.
204  rules->setTiming (enemyCount);
205  rules->getDigTimes (digCycleTime, digCycleCount);
206 
207  // Create the hero (always sprite 0), with the proper timing.
208  for (int j = wall ; j < levelHeight + wall; j++) {
209  for (int i = wall; i < levelWidth + wall; i++) {
210  char type = grid->cellType (i, j);
211  if (type == HERO) {
212  if (hero == 0) {
213  targetI = i;
214  targetJ = j;
215  heroId = emit makeSprite (HERO, i, j);
216  hero = new KGrHero (this, grid, i, j, heroId, rules);
217  hero->setNuggets (nuggets);
218  if ((controlMode == MOUSE) || (controlMode == LAPTOP)) {
219  emit setMousePos (targetI, targetJ);
220  }
221  grid->changeCellAt (i, j, FREE); // Hero now a sprite.
222  }
223  }
224  }
225  }
226 
227  // Create the enemies (sprites 1-n), with the proper timing.
228  for (int j = wall ; j < levelHeight + wall; j++) {
229  for (int i = wall; i < levelWidth + wall; i++) {
230  char type = grid->cellType (i, j);
231  if (type == ENEMY) {
232  KGrEnemy * enemy;
233  int id = emit makeSprite (ENEMY, i, j);
234  enemy = new KGrEnemy (this, grid, i, j, id, rules);
235  enemies.append (enemy);
236  grid->changeCellAt (i, j, FREE); // Enemy now a sprite.
237  grid->setEnemyOccupied (i, j, id);
238  }
239  }
240  }
241 
242  // Connect the hero's and enemies' efforts to the graphics.
243  connect (this, SIGNAL (gotGold(int,int,int,bool,bool)),
244  view->gameScene(), SLOT (gotGold(int,int,int,bool,bool)));
245 
246  // Connect mouse-clicks from KGrCanvas to digging slot.
247  connect (view, SIGNAL (mouseClick(int)), SLOT (doDig(int)));
248 
249  // Connect the hero and enemies (if any) to the animation code.
250  connect (hero, SIGNAL (startAnimation (int, bool, int, int,
251  int, Direction, AnimationType)),
252  view->gameScene(), SLOT (startAnimation (int, bool, int, int,
253  int, Direction, AnimationType)));
254 
255  foreach (KGrEnemy * enemy, enemies) {
256  connect (enemy, SIGNAL (startAnimation (int, bool, int, int,
257  int, Direction, AnimationType)),
258  view->gameScene(), SLOT (startAnimation (int, bool, int, int,
259  int, Direction, AnimationType)));
260  }
261 
262  // Connect the scoring.
263  connect (hero, SIGNAL (incScore(int)),
264  game, SLOT (incScore(int)));
265  foreach (KGrEnemy * enemy, enemies) {
266  connect (enemy, SIGNAL (incScore(int)),
267  game, SLOT (incScore(int)));
268  }
269 
270  // Connect the sounds.
271  connect (hero, SIGNAL (soundSignal(int,bool)),
272  game, SLOT (playSound(int,bool)));
273 
274  // Connect the level player to the animation code (for use with dug bricks).
275  connect (this, SIGNAL (startAnimation (int, bool, int, int,
276  int, Direction, AnimationType)),
277  view->gameScene(), SLOT (startAnimation (int, bool, int, int,
278  int, Direction, AnimationType)));
279 
280  connect (this, SIGNAL (deleteSprite(int)),
281  view->gameScene(), SLOT (deleteSprite(int)));
282 
283  // Connect the grid to the view, to show hidden ladders when the time comes.
284  connect (grid, SIGNAL (showHiddenLadders(QList<int>,int)),
285  view->gameScene(), SLOT (showHiddenLadders(QList<int>,int)));
286 
287  // Connect and start the timer. The tick() slot emits signal animation(),
288  // so there is just one time-source for the model and the view.
289 
290  timer = new KGrTimer (this, TickTime); // TickTime def in kgrglobals.h.
291  if (gameFrozen) {
292  timer->pause(); // Pause is ON as level starts.
293  }
294 
295  connect (timer, SIGNAL (tick(bool,int)), this, SLOT (tick(bool,int)));
296  connect (this, SIGNAL (animation(bool)),
297  view->gameScene(), SLOT (animate(bool)));
298 
299  if (! playback) {
300  // Allow some time to view the level before starting a replay.
301  recordInitialWaitTime (1500); // 1500 msec or 1.5 sec.
302  }
303 }
304 
305 void KGrLevelPlayer::startDigging (Direction diggingDirection)
306 {
307  int digI = 1;
308  int digJ = 1;
309 
310  // We need the hero to decide if he CAN dig and if so, where.
311  if (hero->dig (diggingDirection, digI, digJ)) {
312  // The hero can dig as requested: the chosen brick is at (digI, digJ).
313  grid->changeCellAt (digI, digJ, HOLE);
314 
315  // Start the brick-opening animation (non-repeating).
316  int id = emit makeSprite (BRICK, digI, digJ);
317  emit startAnimation (id, false, digI, digJ,
318  (digOpeningCycles * digCycleTime), STAND, OPEN_BRICK);
319 
320  DugBrick * thisBrick = new DugBrick;
321  DugBrick brick = {id, digCycleTime, digI, digJ,
322  (digCycleCount + digOpeningCycles + digClosingCycles - 1),
323  t.elapsed()}; // IDW test
324  (* thisBrick) = brick;
325  dugBricks.append (thisBrick);
326  }
327 }
328 
329 void KGrLevelPlayer::processDugBricks (const int scaledTime)
330 {
331  DugBrick * dugBrick;
332  QMutableListIterator<DugBrick *> iterator (dugBricks);
333 
334  while (iterator.hasNext()) {
335  dugBrick = iterator.next();
336  dugBrick->cycleTimeLeft -= scaledTime;
337  if (dugBrick->cycleTimeLeft < scaledTime) {
338  dugBrick->cycleTimeLeft += digCycleTime;
339  if (--dugBrick->countdown == digClosingCycles) {
340  // Start the brick-closing animation (non-repeating).
341  emit startAnimation (dugBrick->id, false,
342  dugBrick->digI, dugBrick->digJ,
343  (digClosingCycles * digCycleTime),
344  STAND, CLOSE_BRICK);
345  }
346  if (dugBrick->countdown == digKillingTime) {
347  // Close the hole and maybe capture the hero or an enemy.
348  grid->changeCellAt (dugBrick->digI, dugBrick->digJ, BRICK);
349  }
350  if (dugBrick->countdown <= 0) {
351  // Dispose of the dug brick and remove it from the list.
352  emit deleteSprite (dugBrick->id);
353  delete dugBrick;
354  iterator.remove();
355  }
356  }
357  }
358 }
359 
360 void KGrLevelPlayer::prepareToPlay()
361 {
362  if ((controlMode == MOUSE) || (controlMode == LAPTOP)) {
363  emit setMousePos (targetI, targetJ);
364  }
365  playState = Ready;
366 }
367 
368 void KGrLevelPlayer::pause (bool stop)
369 {
370  if (stop) {
371  timer->pause();
372  }
373  else {
374  timer->resume();
375  }
376 }
377 
378 void KGrLevelPlayer::setTarget (int pointerI, int pointerJ)
379 {
380  // Mouse or other pointer device (eg. laptop touchpad) controls the hero.
381  switch (playState) {
382  case NotReady:
383  // Ignore the pointer until KGrLevelPlayer is ready to start.
384  break;
385  case Ready:
386  // Wait until the human player is ready to start playing.
387  if ((pointerI == targetI) && (pointerJ == targetJ)) {
388  // The pointer is still over the hero: do not start playing yet.
389  break;
390  }
391  // The pointer moved: fall into "case Playing:" and start playing.
392  else if (! playback) { // TODO - Remove debugging code (3 lines).
393  T = 0;
394  }
395  playState = Playing;
396  case Playing:
397  // The human player is playing now.
398  if (! playback) {
399  record (3, pointerI, pointerJ);
400  }
401  targetI = pointerI;
402  targetJ = pointerJ;
403  break;
404  }
405 }
406 
407 void KGrLevelPlayer::doDig (int button)
408 {
409  // Click to end demo/playback mode.
410  if (playback) {
411  interruptPlayback();
412  return;
413  }
414 
415  // If not ready or game control is not by mouse, ignore mouse-clicks.
416  if ((playState == NotReady) || (controlMode != MOUSE)) {
417  return;
418  }
419 
420  uchar recordByte = 0;
421  playState = Playing;
422  switch (button) {
423  case Qt::LeftButton:
424  recordByte = DIRECTION_CODE + DIG_LEFT;
425  startDigging (DIG_LEFT);
426  break;
427  case Qt::RightButton:
428  recordByte = DIRECTION_CODE + DIG_RIGHT;
429  startDigging (DIG_RIGHT);
430  break;
431  default:
432  break;
433  }
434  if (recordByte != 0) {
435  // Record the digging action.
436  record (1, recordByte);
437  }
438 }
439 
440 void KGrLevelPlayer::setDirectionByKey (const Direction dirn,
441  const bool pressed)
442 
443 {
444  // Keystrokes control the hero. KGrGame should avoid calling this during
445  // playback, but better to be safe ...
446  if (playback || (playState == NotReady) || (controlMode == MOUSE)) {
447  return;
448  }
449 
450  if ((dirn == DIG_LEFT) || (dirn == DIG_RIGHT)) {
451  // Control mode is KEYBOARD or LAPTOP (hybrid: pointer + dig-keys).
452  if (playState == Ready) {
453  playState = Playing;
454  T = 0;
455  }
456  if (controlMode == KEYBOARD) {
457 // IDW What happens here if keyboard option is HOLD_KEY? What *should* happen?
458  newDirection = STAND; // Stop a keyboard move when digging.
459  }
460  startDigging (dirn);
461  record (1, (uchar) (DIRECTION_CODE + dirn));
462  }
463  else if (controlMode == KEYBOARD) {
464  if (playState == Ready) {
465  playState = Playing;
466  T = 0;
467  }
468  // Start recording and acting on the new direction at the next tick.
469  if ((holdKeyOption == CLICK_KEY) && pressed && (dirn != direction)) {
470  newDirection = dirn;
471  }
472  else if (holdKeyOption == HOLD_KEY) {
473  int sign = pressed ? +1 : -1;
474  dX = dX + sign * movement [dirn][X];
475  dY = dY + sign * movement [dirn][Y];
476  }
477  }
478 }
479 
480 Direction KGrLevelPlayer::getDirection (int heroI, int heroJ)
481 {
482  if ((controlMode == MOUSE) || (controlMode == LAPTOP)) {
483  int index = (playback) ? recIndex : recIndex - 2;
484  dbe2 "T %04d recIndex %03d hero at [%02d, %02d] aiming at [%02d, %02d]\n",
485  T, index, heroI, heroJ, targetI, targetJ);
486 
487  // If using a pointer device, calculate the hero's next direction,
488  // starting from last pointer position and hero's current position.
489 
490  direction = setDirectionByDelta (targetI - heroI, targetJ - heroJ,
491  heroI, heroJ);
492  }
493  else if ((controlMode == KEYBOARD) && (holdKeyOption == HOLD_KEY)) {
494 
495  // If using the hold/release key option, resolve diagonal directions
496  // (if there are multi-key holds) into either horizontal or vertical.
497 
498  direction = setDirectionByDelta (dX, dY, heroI, heroJ);
499  dbe2 "T %04d recIndex %03d delta [%02d, %02d] "
500  "hero at [%02d, %02d] direction %d\n",
501  T, recIndex - 1, dX, dY, heroI, heroJ, direction);
502  }
503 
504  return direction;
505 }
506 
507 Direction KGrLevelPlayer::setDirectionByDelta (const int di, const int dj,
508  const int heroI, const int heroJ)
509 {
510  Direction dirn = STAND;
511 
512  if ((dj > 0) && (grid->heroMoves (heroI, heroJ) & dFlag [DOWN])) {
513  dirn = DOWN;
514  }
515  else if ((dj < 0) && (grid->heroMoves (heroI, heroJ) & dFlag [UP])) {
516  dirn = UP;
517  }
518  else if (di > 0) {
519  dirn = RIGHT;
520  }
521  else if (di < 0) {
522  dirn = LEFT;
523  }
524  else { // Note: di is zero, but dj is not necessarily zero.
525  dirn = STAND;
526  }
527  return dirn;
528 }
529 
530 void KGrLevelPlayer::recordInitialWaitTime (const int ms)
531 {
532  // Allow a pause for viewing when playback starts.
533  recCount = ms / TickTime; // Convert milliseconds-->ticks.
534  if (controlMode == KEYBOARD) {
535  recording->content [recIndex++] = (uchar) (DIRECTION_CODE +
536  NO_DIRECTION);
537  recording->content [recIndex] = (uchar) recCount;
538  recording->content [recIndex + 1] = (uchar) END_CODE;
539  }
540  else {
541  recording->content [recIndex++] = (uchar) targetI;
542  recording->content [recIndex++] = (uchar) targetJ;
543  recording->content [recIndex] = (uchar) recCount;
544  recording->content [recIndex + 1] = (uchar) END_CODE;
545  }
546 }
547 
548 void KGrLevelPlayer::record (const int bytes, const int n1, const int n2)
549 {
550  if (playback) {
551  return;
552  }
553 
554  // Check for repetition of a previous direction-key or pointer posn. (I, J).
555  if (recIndex > 2)
556  dbe3 "recCount %d bytes %d n1 %d n2 %d [recIndex-1] %d [recIndex-2] %d\n",
557  recCount, bytes, n1, n2, (uchar) recording->content.at (recIndex - 1),
558  (uchar) recording->content.at (recIndex - 2));
559  if ((recCount > 0) && (bytes > 1) && (recCount < (END_CODE - 1)) &&
560  (((bytes == 2) && (n1 == (uchar) recording->content [recIndex - 1])) ||
561  ((bytes == 3) && (n1 == (uchar) recording->content [recIndex - 2]) &&
562  (n2 == (uchar) recording->content [recIndex - 1]))
563  )) {
564  // Count repetitions, up to a maximum of (END_CODE - 1) = 254.
565  recording->content [recIndex] = (uchar) (++recCount);
566  if (bytes == 2) {
567  dbe2 "T %04d recIndex %03d REC: codes --- %3d %3d - recCount++\n",
568  T, recIndex - 1, (uchar)(recording->content.at (recIndex-1)),
569  (uchar)(recording->content.at (recIndex)));
570  }
571  else if (bytes == 3) {
572  dbe2 "T %04d recIndex %03d REC: codes %3d %3d %3d - recCount++\n",
573  T, recIndex - 2, (uchar)(recording->content.at (recIndex-2)),
574  (uchar)(recording->content.at (recIndex-1)),
575  (uchar)(recording->content.at (recIndex)));
576  }
577  return;
578  }
579 
580  // Record a single code or the first byte of a new doublet or triplet.
581  recCount = 0;
582  recording->content [++recIndex] = (uchar) n1;
583 
584  if (bytes == 3) {
585  // Record another byte for a triplet (i.e. the pointer's J position).
586  recording->content [++recIndex] = (uchar) n2;
587  }
588 
589  if (bytes > 1) {
590  // Record a repetition-count of 1 for a new doublet or triplet.
591  recCount = 1;
592  recording->content [++recIndex] = (uchar) recCount;
593  }
594 
595  switch (bytes) {
596  case 1:
597  dbe2 "T %04d recIndex %03d REC: singleton %3d %x\n",
598  T, recIndex, n1, n1);
599  break;
600  case 2:
601  dbe2 "T %04d recIndex %03d REC: codes %3d %3d %3d - NEW DIRECTION\n",
602  T, recIndex - 1, direction,
603  (uchar)(recording->content.at (recIndex-1)),
604  (uchar)(recording->content.at (recIndex)));
605  break;
606  case 3:
607  dbe2 "T %04d recIndex %03d REC: codes %3d %3d %3d - NEW TARGET\n",
608  T, recIndex - 2, (uchar)(recording->content.at (recIndex-2)),
609  (uchar)(recording->content.at (recIndex-1)),
610  (uchar)(recording->content.at (recIndex)));
611  break;
612  default:
613  break;
614  }
615 
616  // Add the end-of-recording code (= 255).
617  recording->content [recIndex + 1] = (uchar) END_CODE;
618  return;
619 }
620 
621 Direction KGrLevelPlayer::getEnemyDirection (int enemyI, int enemyJ,
622  bool leftRightSearch)
623 {
624  int heroX, heroY, pointsPerCell;
625 
626  pointsPerCell = hero->whereAreYou (heroX, heroY);
627  return rules->findBestWay (enemyI, enemyJ,
628  heroX / pointsPerCell, heroY / pointsPerCell,
629  grid, leftRightSearch);
630 }
631 
632 bool KGrLevelPlayer::heroCaught (const int heroX, const int heroY)
633 {
634  if (enemies.count() == 0) {
635  return false;
636  }
637  int enemyX, enemyY, pointsPerCell_1;
638  foreach (KGrEnemy * enemy, enemies) {
639  pointsPerCell_1 = enemy->whereAreYou (enemyX, enemyY) - 1;
640  if (((heroX < enemyX) ? ((heroX + pointsPerCell_1) >= enemyX) :
641  (heroX <= (enemyX + pointsPerCell_1))) &&
642  ((heroY < enemyY) ? ((heroY + pointsPerCell_1) > enemyY) :
643  (heroY <= (enemyY + pointsPerCell_1)))) {
644  dbk << "Caught by";
645  enemy->showState();
646  return true;
647  }
648  }
649  return false;
650 }
651 
652 KGrEnemy * KGrLevelPlayer::standOnEnemy (const int spriteId,
653  const int x, const int y)
654 {
655  int minEnemies = (spriteId == heroId) ? 1 : 2;
656  if (enemies.count() < minEnemies) {
657  return 0;
658  }
659  int enemyX, enemyY, pointsPerCell;
660  foreach (KGrEnemy * enemy, enemies) {
661  pointsPerCell = enemy->whereAreYou (enemyX, enemyY);
662  if (((enemyY == (y + pointsPerCell)) ||
663  (enemyY == (y + pointsPerCell - 1))) &&
664  (enemyX > (x - pointsPerCell)) &&
665  (enemyX < (x + pointsPerCell))) {
666  return enemy;
667  }
668  }
669  return 0;
670 }
671 
672 bool KGrLevelPlayer::bumpingFriend (const int spriteId, const Direction dirn,
673  const int gridI, const int gridJ)
674 {
675  int dI = 0;
676  int dJ = 0;
677  switch (dirn) {
678  case LEFT:
679  dI = -1;
680  break;
681  case RIGHT:
682  dI = +1;
683  break;
684  case UP:
685  dJ = -1;
686  break;
687  case DOWN:
688  dJ = +1;
689  break;
690  default:
691  break;
692  }
693 
694  int otherEnemy;
695  if (dI != 0) {
696  otherEnemy = grid->enemyOccupied (gridI + dI, gridJ);
697  if (otherEnemy > 0) {
698  dbk3 << otherEnemy << "at" << (gridI + dI) << gridJ
699  << "dirn" << ((otherEnemy > 0) ?
700  (enemies.at (otherEnemy - 1)->direction()) : 0)
701  << "me" << spriteId << "dirn" << dirn;
702  if (enemies.at (otherEnemy - 1)->direction() != dirn) {
703  dbk3 << spriteId << "wants" << dirn << ":" << otherEnemy
704  << "at" << (gridI + dI) << gridJ << "wants"
705  << (enemies.at (otherEnemy - 1)->direction());
706  return true;
707  }
708  }
709  }
710  if (dJ != 0) {
711  otherEnemy = grid->enemyOccupied (gridI, gridJ + dJ);
712  if (otherEnemy > 0) {
713  dbk3 << otherEnemy << "at" << gridI << (gridJ + dJ)
714  << "dirn" << ((otherEnemy > 0) ?
715  (enemies.at (otherEnemy - 1)->direction()) : 0)
716  << "me" << spriteId << "dirn" << dirn;
717  if (enemies.at (otherEnemy - 1)->direction() != dirn) {
718  dbk3 << spriteId << "wants" << dirn << ":" << otherEnemy
719  << "at" << gridI << (gridJ + dJ) << "wants"
720  << (enemies.at (otherEnemy - 1)->direction());
721  return true;
722  }
723  }
724  }
725  return false;
726 }
727 
728 void KGrLevelPlayer::unstackEnemy (const int spriteId,
729  const int gridI, const int gridJ,
730  const int prevEnemy)
731 {
732  dbe2 "KGrLevelPlayer::unstackEnemy (%02d at [%02d,%02d] prevEnemy %02d)\n",
733  spriteId, gridI, gridJ, prevEnemy);
734  int nextId = grid->enemyOccupied (gridI, gridJ);
735  int prevId;
736  while (nextId > 0) {
737  prevId = enemies.at (nextId - 1)->getPrevInCell();
738  dbe2 "Next %02d prev %02d\n", nextId, prevId);
739  if (prevId == spriteId) {
740  dbe2 " SET IDs - id %02d prev %02d\n", nextId, prevEnemy);
741  enemies.at (nextId - 1)->setPrevInCell (prevEnemy);
742  // break;
743  }
744  nextId = prevId;
745  }
746 }
747 
748 void KGrLevelPlayer::tick (bool missed, int scaledTime)
749 {
750  int i, j;
751  emit getMousePos (i, j);
752  if (i == -2) {
753  return; // The KGoldRunner window is inactive.
754  }
755  if ((i == -1) && (playback || (controlMode != KEYBOARD))) {
756  return; // The pointer is outside the level layout.
757  }
758 
759  if (playback) { // Replay a recorded move.
760  if (! doRecordedMove()) {
761  playback = false;
762  // TODO - Should we emit interruptDemo() in UNEXPECTED_END case?
763  dbk << "Unexpected END_OF_RECORDING - or KILL_HERO ACTION.";
764  return; // End of recording.
765  }
766  }
767  else if ((controlMode == MOUSE) || (controlMode == LAPTOP)) {
768  setTarget (i, j); // Make and record a live pointer-move.
769  }
770  else if (controlMode == KEYBOARD) {
771  if (holdKeyOption == CLICK_KEY) {
772  if (newDirection != direction) {
773  direction = newDirection;
774  }
775  }
776  // If keyboard with holdKey option, record one of nine directions.
777  else if (holdKeyOption == HOLD_KEY) {
778  const Direction d [9] = {UP_LEFT, UP, UP_RIGHT,
779  LEFT, STAND, RIGHT,
780  DOWN_LEFT, DOWN, DOWN_RIGHT};
781  direction = d [(3 * (dY + 1)) + (dX + 1)];
782  }
783  // Record the direction, but do not extend the initial wait-time.
784  if ((direction != NO_DIRECTION) && (playState == Playing)) { // IDW
785 // IDW Need a better condition here. (playState == Playing) was to stop
786 // IDW the HOLD_KEY option recording a whole lot of STAND directions before
787 // IDW the first key is pressed. (direction != NO_DIRECTION) is previous code.
788  record (2, DIRECTION_CODE + direction);
789  }
790  }
791 
792  if (playState != Playing) {
793  return;
794  }
795  T++;
796 
797  if (dugBricks.count() > 0) {
798  processDugBricks (scaledTime);
799  }
800 
801  HeroStatus status = hero->run (scaledTime);
802  if ((status == WON_LEVEL) || (status == DEAD)) {
803  // Unsolicited timer-pause halts animation immediately, regardless of
804  // user-selected state. It's OK: KGrGame deletes KGrLevelPlayer v. soon.
805  timer->pause();
806 
807  // Queued connection ensures KGrGame slot runs AFTER return from here.
808  emit endLevel (status);
809  kDebug() << "END OF LEVEL";
810  return;
811  }
812 
813  foreach (KGrEnemy * enemy, enemies) {
814  enemy->run (scaledTime);
815  }
816 
817  emit animation (missed);
818 }
819 
820 int KGrLevelPlayer::runnerGotGold (const int spriteId,
821  const int i, const int j,
822  const bool hasGold, const bool lost)
823 {
824  if (hasGold) {
825  dbk2 << "GOLD COLLECTED BY" << spriteId << "AT" << i << j;
826  }
827  else if (lost) {
828  dbk2 << "GOLD LOST BY" << spriteId << "AT" << i << j;
829  }
830  else {
831  dbk2 << "GOLD DROPPED BY" << spriteId << "AT" << i << j;
832  }
833  if (! lost) {
834  grid->gotGold (i, j, hasGold); // Record pickup/drop on grid.
835  }
836  emit gotGold (spriteId, i, j, hasGold, lost); // Erase/show gold on screen.
837 
838  // If hero got gold, score, maybe show hidden ladders, maybe end the level.
839  if ((spriteId == heroId) || lost) {
840  if (--nuggets <= 0) {
841  grid->placeHiddenLadders(); // All gold picked up or lost.
842  }
843  }
844  if (lost) {
845  hero->setNuggets (nuggets); // Update hero re lost gold.
846  }
847  return nuggets;
848 }
849 
850 void KGrLevelPlayer::makeReappearanceSequence()
851 {
852  // The idea is to make each possible x co-ord come up once per levelWidth
853  // reappearances of enemies. This is not truly random, but it reduces the
854  // tedium in levels where you must keep killing enemies until a particular
855  // x or range of x comes up (e.g. if they have to collect gold for you).
856 
857  // First put the positions in ascending sequence.
858  for (int k = 0; k < levelWidth; k++) {
859  reappearPos [k] = k + 1;
860  }
861 
862  int z;
863  int left = levelWidth;
864  int temp;
865 
866  // Shuffle the co-ordinates of reappearance positions (1 to levelWidth).
867  for (int k = 0; k < levelWidth; k++) {
868  // Pick a random element from those that are left.
869  z = (int) (randomByte ((uchar) left));
870  // Exchange its value with the last of the ones left.
871  temp = reappearPos [z];
872  reappearPos [z] = reappearPos [left - 1];
873  reappearPos [left - 1] = temp;
874  left--;
875  }
876  dbk2 << "Randoms" << reappearPos;
877  reappearIndex = 0;
878 }
879 
880 void KGrLevelPlayer::enemyReappear (int & gridI, int & gridJ)
881 {
882  bool looking = true;
883  int i, j, k;
884 
885  // Follow Traditional or Scavenger rules: enemies reappear at top.
886  j = rules->reappearRow();
887 
888  // Randomly look for a free spot in the row. Limit the number of tries.
889  for (k = 1; ((k <= 3) && looking); k++) {
890  if (reappearIndex >= levelWidth) {
891  makeReappearanceSequence(); // Get next array of random i.
892  }
893  i = reappearPos [reappearIndex++];
894  switch (grid->cellType (i, j)) {
895  case FREE:
896  case HLADDER:
897  looking = false;
898  break;
899  default:
900  break;
901  }
902  }
903 
904  // If unsuccessful, choose the first free spot in the rows below.
905  while ((j < levelHeight) && looking) {
906  j++;
907  i = 0;
908  while ((i < levelWidth) && looking) {
909  i++;
910  switch (grid->cellType (i, j)) {
911  case FREE:
912  case HLADDER:
913  looking = false;
914  break;
915  default:
916  break;
917  }
918  }
919  }
920  dbk2 << "Reappear at" << i << j;
921  gridI = i;
922  gridJ = j;
923 }
924 
925 uchar KGrLevelPlayer::randomByte (const uchar limit)
926 {
927  if (! playback) {
928  uchar value = randomGen->getLong ((unsigned long) limit);
929  // A zero-byte terminates recording->draws, so add 1 when recording ...
930  dbe2 "Draw %03d, index %04d, limit %02d\n", value, randIndex, limit);
931  recording->draws [randIndex++] = value + 1;
932  return value;
933  }
934  else {
935  dbe2 "Draw %03d, index %04d, limit %02d\n",
936  (recording->draws.at (randIndex) - 1), randIndex, limit);
937  // and subtract 1 when replaying.
938  return ((uchar) recording->draws.at (randIndex++) - 1);
939  }
940 }
941 
942 bool KGrLevelPlayer::doRecordedMove()
943 {
944  int i, j;
945  uchar code = recording->content [recIndex];
946  while (true) {
947  // Check for end of recording.
948  if ((code == END_CODE) || (code == 0)) {
949  dbe2 "T %04d recIndex %03d PLAY - END of recording\n",
950  T, recIndex);
951  emit endLevel (UNEXPECTED_END);
952  return false;
953  }
954 
955  // Simulate recorded mouse movement.
956  if (code < DIRECTION_CODE) {
957  // playState = Playing;
958  if (recCount <= 0) {
959  i = code;
960  j = (uchar)(recording->content [recIndex + 1]);
961  // targetI = code;
962  // targetJ = (uchar)(recording->content [recIndex + 1]);
963  recCount = (uchar)(recording->content [recIndex + 2]);
964  dbe2 "T %04d recIndex %03d PLAY codes %d %d %d - NEW TARGET\n",
965  T, recIndex, i, j, recCount);
966  // T, recIndex, targetI, targetJ, recCount);
967 
968  setTarget (i, j);
969  }
970  else {
971  dbe2 "T %04d recIndex %03d PLAY codes %d %d %d\n",
972  T, recIndex, targetI, targetJ, recCount);
973  }
974  if (--recCount <= 0) {
975  recIndex = recIndex + 3;
976  dbe2 "T %04d recIndex %03d PLAY - next index\n",
977  T, recIndex);
978  }
979  break;
980  }
981 
982  // Simulate a key press or mouse button click.
983  else if (code < MODE_CODE) {
984  code = code - DIRECTION_CODE;
985  if (code != direction) {
986  playState = Playing;
987  }
988  if ((code == DIG_LEFT) || (code == DIG_RIGHT)) {
989  dbe2 "T %04d recIndex %03d PLAY dig code %d\n",
990  T, recIndex, code);
991  startDigging ((Direction) (code));
992  recIndex++;
993  code = recording->content [recIndex];
994  recCount = 0;
995  continue;
996  }
997  else {
998  if (recCount <= 0) {
999  recCount = (uchar)(recording->content [recIndex + 1]);
1000  dbe2 "T %04d recIndex %03d PLAY codes %d %d - KEY PRESS\n",
1001  T, recIndex, code, recCount);
1002  direction = ((Direction) (code));
1003  dX = movement [direction][X];
1004  dY = movement [direction][Y];
1005  }
1006  else {
1007  dbe2 "T %04d recIndex %03d PLAY codes %d %d mode %d\n",
1008  T, recIndex, code, recCount, controlMode);
1009  }
1010  if (--recCount <= 0) {
1011  recIndex = recIndex + 2;
1012  dbe2 "T %04d recIndex %03d PLAY - next index\n",
1013  T, recIndex);
1014  }
1015  }
1016  break;
1017  }
1018 
1019  // Replay a change of control-mode.
1020  else if (code < KEY_OPT_CODE) {
1021  dbe2 "T %04d recIndex %03d PLAY control-mode code %d\n",
1022  T, recIndex, code);
1023  setControlMode (code - MODE_CODE);
1024  recIndex++;
1025  code = recording->content [recIndex];
1026  recCount = 0;
1027  continue;
1028  }
1029 
1030  // Replay a change of keyboard click/hold option.
1031  else if (code < ACTION_CODE) {
1032  dbe2 "T %04d recIndex %03d PLAY key-option code %d\n",
1033  T, recIndex, code);
1034  setHoldKeyOption (code - KEY_OPT_CODE + CLICK_KEY);
1035  recIndex++;
1036  code = recording->content [recIndex];
1037  recCount = 0;
1038  continue;
1039  }
1040 
1041  // Replay an action, such as KILL_HERO.
1042  else if (code < SPEED_CODE) {
1043  if (code == (ACTION_CODE + KILL_HERO)) {
1044  dbe2 "T %04d recIndex %03d PLAY kill-hero code %d\n",
1045  T, recIndex, code);
1046  emit endLevel (DEAD);
1047  return false;
1048  }
1049  }
1050 
1051  // Replay a change of speed.
1052  else {
1053  dbe2 "T %04d recIndex %03d PLAY speed-change code %d\n",
1054  T, recIndex, code);
1055  setTimeScale (code - SPEED_CODE);
1056  recIndex++;
1057  code = recording->content [recIndex];
1058  recCount = 0;
1059  continue;
1060  }
1061  }
1062  return true;
1063 }
1064 
1065 void KGrLevelPlayer::interruptPlayback()
1066 {
1067  // Check if still replaying the wait-time before the first move.
1068  if (playState != Playing) {
1069  return;
1070  }
1071 
1072  uchar code = recording->content [recIndex];
1073  // Check for end-of-recording already reached.
1074  if ((code == END_CODE) || (code == 0)) {
1075  return;
1076  }
1077 
1078 // Start debug stuff.
1079  dbk2 << "recIndex" << recIndex << "recCount" << recCount
1080  << "randIndex" << randIndex;
1081  int ch = 0;
1082  int i = 0;
1083  while (i < recording->content.size()) {
1084  ch = (uchar)(recording->content.at(i));
1085  dbe2 "%03d ", ch);
1086  if (ch == 0)
1087  break;
1088  i++;
1089  }
1090  dbe2 "\n%d bytes\n", i - 1);
1091  i = 0;
1092  while (i < recording->draws.size()) {
1093  ch = (uchar)(recording->draws.at(i));
1094  dbe2 "%03d ", ch);
1095  if (ch == 0)
1096  break;
1097  i++;
1098  }
1099  dbe2 "\n%d bytes\n", i - 1);
1100 // End debug stuff.
1101 
1102  if (recCount > 0) {
1103  if ((code >= DIRECTION_CODE) && (code < (DIRECTION_CODE + nDirections)))
1104  {
1105  // Set keyboard counter to show how many ticks have been replayed.
1106  recCount = (uchar)(recording->content [recIndex + 1]) - recCount;
1107  recording->content [recIndex + 1] = (uchar) (recCount);
1108  recIndex = recIndex + 1; // Count here if same key after pause.
1109  }
1110  else if (code < DIRECTION_CODE) {
1111  // Set mouse-move counter to show how many ticks have been replayed.
1112  recCount = (uchar)(recording->content [recIndex + 2]) - recCount;
1113  recording->content [recIndex + 2] = (uchar) (recCount);
1114  recIndex = recIndex + 2; // Count here if mouse in same position.
1115  }
1116  }
1117 
1118  recording->content [recIndex + 1] = END_CODE;
1119  for (int i = (recIndex + 2); i < recording->content.size(); i++) {
1120  recording->content [i] = 0;
1121  }
1122  for (int i = randIndex; i < recording->draws.size(); i++) {
1123  recording->draws [i] = 0;
1124  }
1125 
1126 // Start debug stuff.
1127  dbk2 << "recIndex" << recIndex << "recCount" << recCount
1128  << "randIndex" << randIndex;
1129  i = 0;
1130  while (i < recording->content.size()) {
1131  ch = (uchar)(recording->content.at(i));
1132  dbe2 "%03d ", ch);
1133  if (ch == 0)
1134  break;
1135  i++;
1136  }
1137  dbe2 "\n%d bytes\n", i - 1);
1138  i = 0;
1139  while (i < recording->draws.size()) {
1140  ch = (uchar)(recording->draws.at(i));
1141  dbe2 "%03d ", ch);
1142  if (ch == 0)
1143  break;
1144  i++;
1145  }
1146  dbe2 "\n%d bytes\n", i - 1);
1147 // End debug stuff.
1148 
1149  playback = false;
1150  emit interruptDemo();
1151  dbk << "INTERRUPT - emit interruptDemo();";
1152 }
1153 
1154 void KGrLevelPlayer::killHero()
1155 {
1156  if (! playback) {
1157  // Record that KILL_HERO is how the level ended.
1158  record (1, ACTION_CODE + KILL_HERO);
1159 
1160  emit endLevel (DEAD);
1161  kDebug() << "END OF LEVEL";
1162  }
1163 }
1164 
1165 void KGrLevelPlayer::setControlMode (const int mode)
1166 {
1167  controlMode = mode;
1168 
1169  if (! playback) {
1170  // Record the change of mode.
1171  record (1, MODE_CODE + mode);
1172  }
1173 }
1174 
1175 void KGrLevelPlayer::setHoldKeyOption (const int option)
1176 {
1177  holdKeyOption = option;
1178 
1179  if (! playback) {
1180  // Record the change of keyboard click/hold option.
1181  record (1, KEY_OPT_CODE + option - CLICK_KEY);
1182  }
1183 }
1184 
1185 void KGrLevelPlayer::setTimeScale (const int timeScale)
1186 {
1187  timer->setScale ((float) (timeScale * 0.1));
1188 
1189  if (! playback) {
1190  record (1, SPEED_CODE + timeScale);
1191  }
1192 }
1193 
1194 /******************************************************************************/
1195 /************************** AUTHORS' DEBUGGING AIDS **************************/
1196 /******************************************************************************/
1197 
1198 void KGrLevelPlayer::dbgControl (int code)
1199 {
1200  switch (code) {
1201  case DO_STEP:
1202  timer->step(); // Do one timer step only.
1203  break;
1204  case BUG_FIX:
1205  bugFix(); // Turn a bug fix on/off dynamically.
1206  break;
1207  case LOGGING:
1208  startLogging(); // Turn logging on/off.
1209  break;
1210  case S_POSNS:
1211  showFigurePositions(); // Show everybody's co-ordinates.
1212  break;
1213  case S_HERO:
1214  hero->showState(); // Show hero's co-ordinates and state.
1215  break;
1216  case S_OBJ:
1217  showObjectState(); // Show an object's state.
1218  break;
1219  default:
1220  showEnemyState (code - ENEMY_0); // Show enemy co-ords and state.
1221  break;
1222  }
1223 }
1224 
1225 void KGrLevelPlayer::bugFix()
1226 {
1227  // Toggle a bug fix on/off dynamically.
1228  KGrGame::bugFix = (KGrGame::bugFix) ? false : true;
1229  fprintf (stderr, "%s", (KGrGame::bugFix) ? "\n" : "");
1230  fprintf (stderr, ">> Bug fix is %s\n", (KGrGame::bugFix) ? "ON" : "OFF\n");
1231 }
1232 
1233 void KGrLevelPlayer::startLogging()
1234 {
1235  // Toggle logging on/off dynamically.
1236  KGrGame::logging = (KGrGame::logging) ? false : true;
1237  fprintf (stderr, "%s", (KGrGame::logging) ? "\n" : "");
1238  fprintf (stderr, ">> Logging is %s\n", (KGrGame::logging) ? "ON" : "OFF\n");
1239 }
1240 
1241 void KGrLevelPlayer::showFigurePositions()
1242 {
1243  hero->showState();
1244  foreach (KGrEnemy * enemy, enemies) {
1245  enemy->showState();
1246  }
1247 }
1248 
1249 void KGrLevelPlayer::showObjectState()
1250 {
1251  int i = targetI;
1252  int j = targetJ;
1253  char here = grid->cellType (i, j);
1254  Flags access = grid->heroMoves (i, j);
1255  int enemyId = grid->enemyOccupied (i, j);
1256 
1257  int enter = (access & ENTERABLE) ? 1 : 0;
1258  int stand = (access & dFlag [STAND]) ? 1 : 0;
1259  int u = (access & dFlag [UP]) ? 1 : 0;
1260  int d = (access & dFlag [DOWN]) ? 1 : 0;
1261  int l = (access & dFlag [LEFT]) ? 1 : 0;
1262  int r = (access & dFlag [RIGHT]) ? 1 : 0;
1263  fprintf (stderr,
1264  "[%02d,%02d] [%c] %02x E %d S %d U %d D %d L %d R %d occ %02d\n",
1265  i, j, here, access, enter, stand, u, d, l, r, enemyId);
1266 
1267  Flags eAccess = grid->enemyMoves (i, j);
1268  if (eAccess != access) {
1269  access = eAccess;
1270  enter = (access & ENTERABLE) ? 1 : 0;
1271  stand = (access & dFlag [STAND]) ? 1 : 0;
1272  u = (access & dFlag [UP]) ? 1 : 0;
1273  d = (access & dFlag [DOWN]) ? 1 : 0;
1274  l = (access & dFlag [LEFT]) ? 1 : 0;
1275  r = (access & dFlag [RIGHT]) ? 1 : 0;
1276  fprintf (stderr,
1277  "[%02d,%02d] [%c] %02x E %d S %d U %d D %d L %d R %d Enemy\n",
1278  i, j, here, access, enter, stand, u, d, l, r);
1279  }
1280 }
1281 
1282 void KGrLevelPlayer::showEnemyState (int enemyId)
1283 {
1284  if (enemyId < enemies.count()) {
1285  enemies.at(enemyId)->showState();
1286  }
1287 }
1288 
1289 
1290 #include "kgrlevelplayer.moc"
KGrLevelPlayer::prepareToPlay
void prepareToPlay()
Indicate that setup is complete and the human player can start playing at any time, by moving the pointer device or pressing a key.
Definition: kgrlevelplayer.cpp:360
KGrLevelPlayer::unstackEnemy
void unstackEnemy(const int spriteId, const int gridI, const int gridJ, const int prevEnemy)
Helper function to remove an enemy from among several stacked in a cell.
Definition: kgrlevelplayer.cpp:728
HeroStatus
HeroStatus
Definition: kgrglobals.h:219
UNEXPECTED_END
Definition: kgrglobals.h:220
KGrLevelPlayer::heroCaught
bool heroCaught(const int heroX, const int heroY)
Helper function to determine whether the hero has collided with an enemy and must lose a life (unless...
Definition: kgrlevelplayer.cpp:632
KGrLevelPlayer::endLevel
void endLevel(const int result)
QList::clear
void clear()
KGrLevelPlayer::enemyReappear
void enemyReappear(int &gridI, int &gridJ)
Helper function to determine where an enemy should reappear after being trapped in a brick...
Definition: kgrlevelplayer.cpp:880
dbe1
#define dbe1
Definition: kgrdebug.h:34
OPEN_BRICK
Definition: kgrglobals.h:208
KGrRecording::rules
char rules
Rules that applied at time of recording.
Definition: kgrglobals.h:120
KGrGame::logging
static bool logging
Definition: kgrgame.h:63
KGrRuleBook::reappearRow
int reappearRow() const
Definition: kgrrulebook.h:41
kgrdebug.h
KGrLevelGrid::enemyOccupied
int enemyOccupied(int i, int j)
Definition: kgrlevelgrid.h:50
ENEMY_0
Definition: kgrglobals.h:215
KGrLevelGrid::heroMoves
Flags heroMoves(int i, int j)
Definition: kgrlevelgrid.h:38
KGrLevelGrid::placeHiddenLadders
void placeHiddenLadders()
Definition: kgrlevelgrid.cpp:197
KGrTimer::setScale
void setScale(const float pScale)
Definition: kgrtimer.h:35
KGrLevelGrid::cellType
char cellType(int i, int j)
Definition: kgrlevelgrid.h:34
KGrLevelPlayer::~KGrLevelPlayer
~KGrLevelPlayer()
Definition: kgrlevelplayer.cpp:70
dbk3
#define dbk3
Definition: kgrdebug.h:26
KGrRecording::controlMode
int controlMode
Control mode during recording (mouse, etc).
Definition: kgrglobals.h:132
QByteArray::at
char at(int i) const
kgrtimer.h
KGrLevelGrid
Definition: kgrlevelgrid.h:27
KGrLevelGrid::calculateAccess
void calculateAccess(bool pRunThruHole)
Definition: kgrlevelgrid.cpp:87
kgrlevelgrid.h
TickTime
const int TickTime
Definition: kgrglobals.h:217
HERO
const char HERO
Definition: kgrglobals.h:31
QVector::fill
QVector< T > & fill(const T &value, int size)
KGrRuleBook::runThruHole
bool runThruHole() const
Definition: kgrrulebook.h:39
KGrLevelPlayer::setHoldKeyOption
void setHoldKeyOption(const int option)
Change the keyboard click/hold option during play.
Definition: kgrlevelplayer.cpp:1175
QList::at
const T & at(int i) const
KGrView::gameScene
KGrScene * gameScene() const
Definition: kgrview.h:37
S_POSNS
Definition: kgrglobals.h:214
KGrLevelPlayer::runnerGotGold
int runnerGotGold(const int spriteId, const int i, const int j, const bool hasGold, const bool lost=false)
Helper function for an enemy to pick up or drop gold or the hero to collect gold. ...
Definition: kgrlevelplayer.cpp:820
KGrTimer::step
void step()
Definition: kgrtimer.cpp:55
kgrrulebook.h
DIG_LEFT
Definition: kgrglobals.h:175
WON_LEVEL
Definition: kgrglobals.h:220
S_HERO
Definition: kgrglobals.h:214
KGrTimer::resume
void resume()
Definition: kgrtimer.cpp:48
DOWN_RIGHT
Definition: kgrglobals.h:176
SPEED_CODE
#define SPEED_CODE
Definition: kgrglobals.h:149
KGrLevelPlayer::pause
void pause(bool stop)
Pause or resume the gameplay in this level.
Definition: kgrlevelplayer.cpp:368
dbe2
#define dbe2
Definition: kgrdebug.h:35
KGrLevelGrid::enemyMoves
Flags enemyMoves(int i, int j)
Definition: kgrlevelgrid.h:42
NO_DIRECTION
Definition: kgrglobals.h:175
dbgLevel
static int dbgLevel
Definition: kgrdebug.h:21
KGrLevelPlayer::interruptPlayback
void interruptPlayback()
Stop playback of a recorded level and adjust the content of the recording so that the user can contin...
Definition: kgrlevelplayer.cpp:1065
KGrLevelPlayer::animation
void animation(bool missed)
Requests the view to update animated sprites.
KGrScene::setGoldEnemiesRule
void setGoldEnemiesRule(bool showIt)
Definition: kgrscene.h:128
KGrLevelPlayer::bumpingFriend
bool bumpingFriend(const int spriteId, const Direction dirn, const int gridI, const int gridJ)
Helper function to determine whether an enemy is colliding with another enemy.
Definition: kgrlevelplayer.cpp:672
TraditionalRules
const char TraditionalRules
Codes for the rules of the selected game and level.
Definition: kgrglobals.h:65
END_CODE
#define END_CODE
Definition: kgrglobals.h:150
S_OBJ
Definition: kgrglobals.h:214
LAPTOP
Definition: kgrglobals.h:161
kgrlevelplayer.h
KGrLevelGrid::changeCellAt
void changeCellAt(const int i, const int j, const char type)
Definition: kgrlevelgrid.cpp:113
KGrHero
This class models the behaviour of the hero.
Definition: kgrrunner.h:148
Direction
Direction
Definition: kgrglobals.h:174
KGrRuleBook::getDigTimes
void getDigTimes(int &digTime, int &digCounter)
Definition: kgrrulebook.h:58
LEFT
Definition: kgrglobals.h:174
X
Definition: kgrglobals.h:187
QTime::elapsed
int elapsed() const
KGrLevelGrid::setEnemyOccupied
void setEnemyOccupied(int i, int j, const int spriteId)
Definition: kgrlevelgrid.h:54
QList::count
int count(const T &value) const
QList::append
void append(const T &value)
KGrLevelPlayer::deleteSprite
void deleteSprite(const int spriteId)
NUGGET
const char NUGGET
Definition: kgrglobals.h:37
ScavengerRules
const char ScavengerRules
Definition: kgrglobals.h:67
kgrrunner.h
KGrLevelPlayer::getMousePos
void getMousePos(int &i, int &j)
QObject
KGrHero::run
HeroStatus run(const int scaledTime)
Makes the hero run, under control of a pointer or the keyboard and guided by the layout of the grid...
Definition: kgrrunner.cpp:214
KGrLevelPlayer::dbgControl
void dbgControl(int code)
Implement author's debugging aids, which are activated only if the level is paused and the KConfig fi...
Definition: kgrlevelplayer.cpp:1198
UP_LEFT
Definition: kgrglobals.h:176
BUG_FIX
Definition: kgrglobals.h:214
KGrLevelPlayer::gotGold
void gotGold(const int spriteId, const int i, const int j, const bool hasGold, const bool lost)
KGrRecording
KGrRecording structure: contains a record of play in a KGoldrunner level.
Definition: kgrglobals.h:115
CLOSE_BRICK
Definition: kgrglobals.h:208
movement
const int movement[EndDirection][nAxes]
Definition: kgrglobals.h:189
KGrLevelPlayer::setDirectionByKey
void setDirectionByKey(const Direction dirn, const bool pressed)
Set a direction for the hero to move or dig when using keyboard control.
Definition: kgrlevelplayer.cpp:440
MOUSE
Definition: kgrglobals.h:161
KGrLevelPlayer::setTimeScale
void setTimeScale(const int timeScale)
Set the overall speed of gameplay.
Definition: kgrlevelplayer.cpp:1185
Y
Definition: kgrglobals.h:187
KGrTimer
Definition: kgrtimer.h:25
QString
QList< int >
KGrRunner::whereAreYou
int whereAreYou(int &x, int &y)
Returns the exact position of a runner (in grid-points or cell sub-divisions) and the number of grid-...
Definition: kgrrunner.h:68
HLADDER
const char HLADDER
Definition: kgrglobals.h:35
KGrRuleBook::findBestWay
virtual Direction findBestWay(const int eI, const int eJ, const int hI, const int hJ, KGrLevelGrid *pGrid, bool leftRightSearch=true)=0
HOLD_KEY
Definition: kgrglobals.h:162
KGrLevelPlayer::randomByte
uchar randomByte(const uchar limit)
Helper function to provide enemies with random numbers for reappearing and deciding whether to pick u...
Definition: kgrlevelplayer.cpp:925
LOGGING
Definition: kgrglobals.h:214
KGrLevelPlayer::getDirection
Direction getDirection(int heroI, int heroJ)
Helper function for the hero to find his next direction when using mouse or touchpad control...
Definition: kgrlevelplayer.cpp:480
nDirections
Definition: kgrglobals.h:174
KGrScavengerRules
Definition: kgrrulebook.h:137
KGrKGoldrunnerRules
Definition: kgrrulebook.h:117
KGrLevelPlayer::KGrLevelPlayer
KGrLevelPlayer(QObject *parent, KRandomSequence *pRandomGen)
The constructor of KGrLevelPlayer.
Definition: kgrlevelplayer.cpp:38
KGrHero::showState
void showState()
Implements the author's debugging aid that shows the hero's state.
Definition: kgrrunner.cpp:344
UP_RIGHT
Definition: kgrglobals.h:176
DOWN_LEFT
Definition: kgrglobals.h:176
dbe3
#define dbe3
Definition: kgrdebug.h:36
ENEMY
const char ENEMY
Definition: kgrglobals.h:29
KGrTraditionalRules
Definition: kgrrulebook.h:92
KGoldrunnerRules
const char KGoldrunnerRules
Definition: kgrglobals.h:66
KGrLevelPlayer::makeSprite
int makeSprite(char spriteType, int i, int j)
BRICK
const char BRICK
Definition: kgrglobals.h:33
KILL_HERO
Definition: kgrglobals.h:153
KGrHero::setNuggets
void setNuggets(const int nGold)
Tells the hero how many gold nuggets are remaining.
Definition: kgrrunner.h:207
kgrscene.h
dbk2
#define dbk2
Definition: kgrdebug.h:25
KGrLevelPlayer::killHero
void killHero()
If not in playback mode, add a code to the recording and kill the hero.
Definition: kgrlevelplayer.cpp:1154
kgrview.h
UP
Definition: kgrglobals.h:174
KGrLevelPlayer::paintCell
void paintCell(int i, int j, char tileType)
Requests the view to display a particular type of tile at a particular cell, or make it empty and sho...
KGrRecording::draws
QByteArray draws
The random numbers used during play.
Definition: kgrglobals.h:135
ACTION_CODE
#define ACTION_CODE
Definition: kgrglobals.h:148
DIRECTION_CODE
#define DIRECTION_CODE
Definition: kgrglobals.h:145
KGrHero::dig
bool dig(const Direction dirn, int &digI, int &digJ)
Decides whether the hero can dig as is required by pressing a key or a mouse-button.
Definition: kgrrunner.cpp:305
FBRICK
const char FBRICK
Definition: kgrglobals.h:34
KEYBOARD
Definition: kgrglobals.h:161
KGrTimer::pause
void pause()
Definition: kgrtimer.cpp:43
HOLE
const char HOLE
Definition: kgrglobals.h:40
MODE_CODE
#define MODE_CODE
Definition: kgrglobals.h:146
KGrLevelPlayer::setMousePos
void setMousePos(const int i, const int j)
QMutableListIterator
KGrGame::bugFix
static bool bugFix
Definition: kgrgame.h:62
KGrView
Definition: kgrview.h:27
KGrLevelGrid::gotGold
void gotGold(const int i, const int j, const bool runnerHasGold)
Definition: kgrlevelgrid.h:46
ConcreteWall
const int ConcreteWall
Definition: kgrglobals.h:168
KGrRuleBook::setTiming
void setTiming(const int enemyCount=0)
Definition: kgrrulebook.cpp:40
KGrRecording::width
int width
Width of grid, in cells (at rec time).
Definition: kgrglobals.h:124
KGrLevelPlayer::interruptDemo
void interruptDemo()
KGrLevelPlayer::setControlMode
void setControlMode(const int mode)
Change the input-mode during play.
Definition: kgrlevelplayer.cpp:1165
RIGHT
Definition: kgrglobals.h:174
KGrRecording::keyOption
int keyOption
Click/hold option for keyboard mode.
Definition: kgrglobals.h:133
DEAD
Definition: kgrglobals.h:220
DO_STEP
Definition: kgrglobals.h:214
ENTERABLE
const AccessFlag ENTERABLE
Definition: kgrglobals.h:185
dbk
#define dbk
Definition: kgrdebug.h:23
QTime::start
void start()
KGrRuleBook::enemiesShowGold
bool enemiesShowGold() const
Definition: kgrrulebook.h:44
KGrEnemy::showState
void showState()
Implements the author's debugging aid that shows the enemy's state.
Definition: kgrrunner.cpp:610
DIG_RIGHT
Definition: kgrglobals.h:175
KGrLevelPlayer::startAnimation
void startAnimation(const int spriteId, const bool repeating, const int i, const int j, const int time, const Direction dirn, const AnimationType type)
Requests the view to display an animation of a dug brick at a particular cell, cancelling and superse...
Flags
char Flags
Definition: kgrglobals.h:172
KGrEnemy::run
void run(const int scaledTime)
Makes an enemy run, guided by the position of the hero and the layout of the grid.
Definition: kgrrunner.cpp:378
QByteArray::size
int size() const
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KGrRecording::height
int height
Height of grid, in cells (at rec time).
Definition: kgrglobals.h:125
KGrRecording::content
QByteArray content
The encoded recording of play.
Definition: kgrglobals.h:134
KGrLevelPlayer::getEnemyDirection
Direction getEnemyDirection(int enemyI, int enemyJ, bool leftRightSearch)
Helper function for an enemy to find his next direction, based on where the hero is and the search al...
Definition: kgrlevelplayer.cpp:621
kgrgame.h
STAND
Definition: kgrglobals.h:174
KGrLevelPlayer::setTarget
void setTarget(int pointerI, int pointerJ)
Set a point for the hero to aim at when using mouse or touchpad control.
Definition: kgrlevelplayer.cpp:378
AnimationType
AnimationType
Definition: kgrglobals.h:203
KGrEnemy
This class models the behaviour of an enemy.
Definition: kgrrunner.h:229
DOWN
Definition: kgrglobals.h:174
FREE
const char FREE
Definition: kgrglobals.h:28
KEY_OPT_CODE
#define KEY_OPT_CODE
Definition: kgrglobals.h:147
dFlag
const DirectionFlag dFlag[nDirections]
Definition: kgrglobals.h:178
CLICK_KEY
Definition: kgrglobals.h:162
KGrLevelPlayer::standOnEnemy
KGrEnemy * standOnEnemy(const int spriteId, const int x, const int y)
Helper function to determine whether the hero or an enemy is standing on an enemy's head...
Definition: kgrlevelplayer.cpp:652
KGrLevelPlayer::init
void init(KGrView *view, KGrRecording *pRecording, const bool pPlayback, const bool gameFrozen)
The main initialisation of KGrLevelPlayer.
Definition: kgrlevelplayer.cpp:100
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:18:24 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kgoldrunner

Skip menu "kgoldrunner"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdegames API Reference

Skip menu "kdegames API Reference"
  • granatier
  • kapman
  • kblackbox
  • kgoldrunner
  • kigo
  • kmahjongg
  • KShisen
  • ksquares
  • libkdegames
  •   highscore
  •   libkdegamesprivate
  •     kgame
  • libkmahjongg
  • palapeli
  •   libpala

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal