2 * Copyright (c) 2007, 2008, 2009, Czirkos Zoltan <cirix@fw.hu>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <glib/gi18n.h>
19 #include "caveobject.h"
20 #include "cavesound.h"
22 #include "caveengine.h"
29 #define GAME_INT_INVALID -100
30 /* prepare cave, gfx buffer */
31 #define GAME_INT_LOAD_CAVE -73
32 /* show description/note of cave. */
33 #define GAME_INT_SHOW_STORY -72
34 /* waiting fire button after showing the story. */
35 #define GAME_INT_SHOW_STORY_WAIT -71
36 /* start uncovering */
37 #define GAME_INT_START_UNCOVER -70
38 /* ...70 frames until full uncover... */
39 #define GAME_INT_UNCOVER_ALL -1
40 /* normal running state. */
41 #define GAME_INT_CAVE_RUNNING 0
42 /* add points for remaining time */
43 #define GAME_INT_CHECK_BONUS_TIME 1
44 /* ...2..99 = wait and do nothing, after adding time */
45 #define GAME_INT_WAIT_BEFORE_COVER 2
47 #define GAME_INT_COVER_START 100
48 /* ... 8 frames of cover animation */
49 #define GAME_INT_COVER_ALL 108
51 gboolean gd_wait_before_game_over
; /* wait some time before covering the cave, if there is a game over. main() should set it true for sdl, false for gtk+ */
57 cave_finished_highscore(GdGame
*game
)
59 /* enter to highscore table */
60 gd_add_highscore(game
->original_cave
->highscore
, game
->player_name
, game
->cave_score
);
67 gd_game_free(GdGame
*game
)
73 gd_cave_map_free(game
->gfx_buffer
);
77 gd_cave_free(game
->cave
);
79 /* if we recorded some replays during this run, we check them. we remove those which are too short */
80 if (game
->replays_recorded
) {
84 for (citer
=gd_caveset
; citer
!=NULL
; citer
=citer
->next
) {
85 GdCave
*cave
=(GdCave
*)citer
->data
;
88 /* check replays of all caves */
89 for (riter
=cave
->replays
; riter
!=NULL
; ) {
90 GdReplay
*replay
=(GdReplay
*)riter
->data
;
91 GList
*nextrep
=riter
->next
; /* remember next iter, as we may delete the current */
93 /* if we recorded this replay now, and it is too short, we delete it */
94 /* but do not delete successful ones! */
95 if (g_list_find(game
->replays_recorded
, replay
) && (replay
->movements
->len
<16) && (!replay
->success
)) {
96 cave
->replays
=g_list_delete_link(cave
->replays
, riter
); /* delete from list */
97 gd_replay_free(replay
); /* also free replay */
103 /* free the list of newly recorded replays, as we checked them */
104 g_list_free(game
->replays_recorded
);
105 game
->replays_recorded
=NULL
;
111 /* add bonus life. if sound enabled, play sound, too. */
113 add_bonus_life(GdGame
*game
, gboolean inform_user
)
115 /* only inform about bonus life when playing a game */
116 /* or when testing the cave (so the user can see that a bonus life can be earned in that cave */
117 if (game
->type
==GD_GAMETYPE_NORMAL
|| game
->type
==GD_GAMETYPE_TEST
)
119 gd_sound_play_bonus_life();
120 game
->bonus_life_flash
=100;
123 /* really increment number of lifes? only in a real game, nowhere else. */
124 if (game
->player_lives
&& game
->player_lives
<gd_caveset_data
->maximum_lives
)
125 /* only add a life, if lives is >0. lives==0 is a test run or a snapshot, no bonus life then. */
126 /* also, obey max number of bonus lives. */
127 game
->player_lives
++;
130 /* increment score of player.
131 flash screen if bonus life
134 increment_score(GdGame
*game
, int increment
)
138 i
=game
->player_score
/gd_caveset_data
->bonus_life_score
;
139 game
->player_score
+=increment
;
140 game
->cave_score
+=increment
;
141 if (game
->replay_record
) /* also record to replay */
142 game
->replay_record
->score
+=increment
;
143 if (game
->player_score
/gd_caveset_data
->bonus_life_score
>i
)
144 add_bonus_life(game
, TRUE
); /* if score crossed bonus_life_score point boundary, player won a bonus life */
147 /* do the things associated with loading a new cave. function creates gfx buffer and the like. */
149 load_cave(GdGame
*game
)
153 /* delete gfx buffer */
154 if (game
->gfx_buffer
)
155 gd_cave_map_free(game
->gfx_buffer
);
156 game
->gfx_buffer
=NULL
;
160 switch (game
->type
) {
161 case GD_GAMETYPE_NORMAL
:
162 /* delete previous cave */
163 gd_cave_free(game
->cave
);
166 /* specified cave from memory; render the cave with a randomly selected seed */
167 game
->original_cave
=gd_return_nth_cave(game
->cave_num
);
168 seed
=g_random_int_range(0, GD_CAVE_SEED_MAX
);
169 game
->cave
=gd_cave_new_rendered(game
->original_cave
, game
->level_num
, seed
); /* for playing: seed=random */
170 gd_cave_setup_for_game(game
->cave
);
171 if (gd_random_colors
) /* new cave-recolor if requested. gameplay->cave is a copy only, so no worries! */
172 gd_cave_set_random_colors(game
->cave
, gd_preferred_palette
);
173 if (game
->cave
->intermission
&& game
->cave
->intermission_instantlife
)
174 add_bonus_life(game
, FALSE
);
177 game
->replay_record
=gd_replay_new();
178 game
->replay_record
->level
=game
->cave
->rendered
-1; /* rendered=0 means not rendered here. 1=level 1 */
179 game
->replay_record
->seed
=game
->cave
->render_seed
;
180 game
->replay_record
->checksum
=gd_cave_adler_checksum(game
->cave
); /* calculate a checksum for this cave */
181 gd_strcpy(game
->replay_record
->recorded_with
, PACKAGE_STRING
);
182 gd_strcpy(game
->replay_record
->player_name
, game
->player_name
);
183 gd_strcpy(game
->replay_record
->date
, gd_get_current_date());
184 game
->original_cave
->replays
=g_list_append(game
->original_cave
->replays
, game
->replay_record
);
185 /* also store the pointer in a list of freshly recorded replays. so we can later check them if they are too short and delete */
186 game
->replays_recorded
=g_list_append(game
->replays_recorded
, game
->replay_record
);
189 case GD_GAMETYPE_TEST
:
190 g_assert(game
->cave
==NULL
);
191 g_assert(game
->original_cave
!=NULL
);
193 seed
=g_random_int_range(0, GD_CAVE_SEED_MAX
);
194 game
->cave
=gd_cave_new_rendered(game
->original_cave
, game
->level_num
, seed
); /* for playing: seed=random */
195 gd_cave_setup_for_game(game
->cave
);
198 case GD_GAMETYPE_SNAPSHOT
:
199 /* if a snapshot or test is requested, that one... just create a copy */
200 /* copy already created in new_game, so nothing to do here. */
201 g_assert(game
->cave
!=NULL
);
202 g_assert(game
->original_cave
==NULL
);
205 case GD_GAMETYPE_REPLAY
:
206 g_assert(game
->replay_from
!=NULL
);
207 g_assert(game
->cave
==NULL
);
209 game
->replay_record
=NULL
;
210 gd_replay_rewind(game
->replay_from
);
211 game
->replay_no_more_movements
=0;
213 game
->cave
=gd_cave_new_rendered(game
->original_cave
, game
->replay_from
->level
, game
->replay_from
->seed
);
214 gd_cave_setup_for_game(game
->cave
);
217 case GD_GAMETYPE_CONTINUE_REPLAY
:
218 g_assert_not_reached();
222 game
->milliseconds_anim
=0;
223 game
->milliseconds_game
=0; /* set game timer to zero, too */
228 gd_create_snapshot(GdGame
*game
)
231 g_return_val_if_fail (game
->cave
!= NULL
, NULL
);
233 /* make an exact copy */
234 snapshot
=gd_cave_new_from_cave(game
->cave
);
238 /* this starts a new game */
240 gd_game_new(const char *player_name
, const int cave
, const int level
)
244 game
=g_new0(GdGame
, 1);
246 gd_strcpy(game
->player_name
, player_name
);
248 game
->level_num
=level
;
250 game
->player_lives
=gd_caveset_data
->initial_lives
;
251 game
->player_score
=0;
253 game
->type
=GD_GAMETYPE_NORMAL
;
254 game
->state_counter
=GAME_INT_LOAD_CAVE
;
256 game
->show_story
=TRUE
;
261 /* starts a new snapshot playing */
263 gd_game_new_snapshot(GdCave
*snapshot
)
267 game
=g_new0(GdGame
, 1);
269 gd_strcpy(game
->player_name
, "");
270 game
->player_lives
=0;
271 game
->player_score
=0;
273 g_assert(snapshot
->rendered
!=0); /* we accept only rendered caves, trivially */
274 game
->cave
=gd_cave_new_from_cave(snapshot
);
276 game
->type
=GD_GAMETYPE_SNAPSHOT
;
277 game
->state_counter
=GAME_INT_LOAD_CAVE
;
282 /* starts a new snapshot playing */
284 gd_game_new_test(GdCave
*cave
, int level
)
288 game
=g_new0(GdGame
, 1);
290 gd_strcpy(game
->player_name
, "");
291 game
->player_lives
=0;
292 game
->player_score
=0;
294 game
->original_cave
=cave
;
295 game
->level_num
=level
;
297 game
->type
=GD_GAMETYPE_TEST
;
298 game
->state_counter
=GAME_INT_LOAD_CAVE
;
303 /* starts a new snapshot playing */
305 gd_game_new_replay(GdCave
*cave
, GdReplay
*replay
)
309 game
=g_new0(GdGame
, 1);
310 gd_strcpy(game
->player_name
, "");
311 game
->player_lives
=0;
312 game
->player_score
=0;
314 game
->original_cave
=cave
;
315 game
->replay_from
=replay
;
317 game
->type
=GD_GAMETYPE_REPLAY
;
318 game
->state_counter
=GAME_INT_LOAD_CAVE
;
325 /* called from iterate_cave, to increment cave and level number.
326 does not load the cave, just sets the new numbers!
329 next_level(GdGame
*game
)
331 game
->cave_num
++; /* next cave */
333 /* if no more caves at this level, back to first one */
334 if (game
->cave_num
>=gd_caveset_count()) {
336 game
->level_num
++; /* but now more difficult */
337 if (game
->level_num
>4)
338 /* if level 5 finished, back to first cave, same difficulty (original game behaviour) */
343 /* if the user fails to solve the cave, the story will not be shown again */
344 game
->show_story
=TRUE
;
352 iterate_cave(GdGame
*game
, GdDirection player_move
, gboolean fire
, gboolean suicide
, gboolean restart
)
354 /* if we are playing a replay, but the user intervents, continue as a snapshot. */
355 /* do not trigger this for fire, as it would not be too intuitive. */
356 if (game
->type
==GD_GAMETYPE_REPLAY
)
357 if (player_move
!=MV_STILL
) {
358 game
->type
=GD_GAMETYPE_CONTINUE_REPLAY
;
359 game
->replay_from
=NULL
;
362 /* ANYTHING EXCEPT A TIMEOUT, WE ITERATE THE CAVE */
363 if (game
->cave
->player_state
!=GD_PL_TIMEOUT
) {
364 /* IF PLAYING FROM REPLAY, OVERWRITE KEYPRESS VARIABLES FROM REPLAY */
365 if (game
->type
==GD_GAMETYPE_REPLAY
) {
368 /* if the user does touch the keyboard, we immediately exit replay, and he can continue playing */
369 result
=gd_replay_get_next_movement(game
->replay_from
, &player_move
, &fire
, &suicide
);
370 /* if could not get move from snapshot, continue from keyboard input. */
372 game
->replay_no_more_movements
++;
373 /* if no more available movements, and the user does not do anything, we cover cave and stop game. */
374 if (game
->replay_no_more_movements
>15)
375 game
->state_counter
=GAME_INT_COVER_START
;
379 gd_cave_iterate(game
->cave
, player_move
, fire
, suicide
);
380 if (game
->replay_record
)
381 gd_replay_store_movement(game
->replay_record
, player_move
, fire
, suicide
);
382 if (game
->cave
->score
)
383 increment_score(game
, game
->cave
->score
);
385 gd_sound_play_cave(game
->cave
);
388 if (game
->cave
->player_state
==GD_PL_EXITED
) {
389 if (game
->cave
->intermission
&& game
->cave
->intermission_rewardlife
&& game
->player_lives
!=0)
390 /* one life extra for completing intermission */
391 add_bonus_life(game
, FALSE
);
392 if (game
->replay_record
)
393 game
->replay_record
->success
=TRUE
;
395 /* start adding points for remaining time */
396 game
->state_counter
=GAME_INT_CHECK_BONUS_TIME
;
397 gd_cave_clear_sounds(game
->cave
);
398 gd_sound_play(game
->cave
, GD_S_FINISHED
); /* play cave finished sound */
399 gd_sound_play_cave(game
->cave
);
403 if (((game
->cave
->player_state
==GD_PL_DIED
|| game
->cave
->player_state
==GD_PL_TIMEOUT
) && fire
) || restart
) {
404 /* player died, and user presses fire -> try again */
405 /* time out -> try again */
406 if (!game
->cave
->intermission
&& game
->player_lives
>0)
407 /* no minus life for intermissions */
408 game
->player_lives
--;
409 if (game
->cave
->intermission
)
410 /* only one chance for intermissions */
413 if (game
->player_lives
==0 && game
->type
==GD_GAMETYPE_NORMAL
) {
414 /* wait some time - this is a game over */
415 if (gd_wait_before_game_over
)
416 game
->state_counter
=GAME_INT_WAIT_BEFORE_COVER
;
418 game
->state_counter
=GAME_INT_COVER_START
; /* jump immediately to covering */
421 /* start cover animation immediately */
422 game
->state_counter
=GAME_INT_COVER_START
;
428 gd_game_main_int(GdGame
*game
, int millisecs_elapsed
, GdDirection player_move
, gboolean fire
, gboolean suicide
, gboolean restart
, gboolean allow_iterate
, gboolean yellowish_draw
, gboolean fast_forward
)
430 gboolean frame
; /* set to true, if this will be an animation frame */
432 GdGameState return_state
;
435 counter_next
=GAME_INT_INVALID
;
436 return_state
=GD_GAME_INVALID_STATE
;
437 game
->milliseconds_anim
+=millisecs_elapsed
; /* keep track of time */
438 frame
=FALSE
; /* set to true, if this will be an animation frame */
439 if (game
->milliseconds_anim
>=40) {
441 game
->milliseconds_anim
-=40;
444 /* cannot be less than uncover start. */
445 if (game
->state_counter
<GAME_INT_LOAD_CAVE
) {
446 g_assert_not_reached();
449 if (game
->state_counter
==GAME_INT_LOAD_CAVE
) {
450 /* do the things associated with loading a new cave. function creates gfx buffer and the like. */
452 return_state
=GD_GAME_NOTHING
;
453 counter_next
=GAME_INT_SHOW_STORY
;
456 /* for normal game, every cave can have a long string of description/story. show that. */
457 if (game
->state_counter
==GAME_INT_SHOW_STORY
) {
458 /* if we have a story... */
459 /* and user settings permit showing that... etc */
460 if (gd_show_story
&& game
->show_story
&& game
->original_cave
&& game
->original_cave
->story
->len
!=0) {
461 gd_cave_clear_sounds(game
->cave
); /* to stop cover sound from previous cave; there should be no cover sound when the user reads the story */
462 gd_sound_play_cave(game
->cave
);
463 counter_next
=GAME_INT_SHOW_STORY_WAIT
;
464 return_state
=GD_GAME_SHOW_STORY
;
465 game
->show_story
=FALSE
; /* so the story will not be shown again, for example when the cave is not solved and played again. */
468 counter_next
=GAME_INT_START_UNCOVER
;
469 return_state
=GD_GAME_NOTHING
;
473 if (game
->state_counter
==GAME_INT_SHOW_STORY_WAIT
) {
474 /* if user presses fire, proceed with loading the cave. */
476 counter_next
=GAME_INT_START_UNCOVER
;
477 return_state
=GD_GAME_NOTHING
;
480 counter_next
=game
->state_counter
;
481 return_state
=GD_GAME_NOTHING
;
485 /* the very beginning. */
486 if (game
->state_counter
==GAME_INT_START_UNCOVER
) {
487 /* create gfx buffer. */
488 game
->gfx_buffer
=gd_cave_map_new(game
->cave
, int);
489 for (y
=0; y
<game
->cave
->h
; y
++)
490 for (x
=0; x
<game
->cave
->w
; x
++)
491 game
->gfx_buffer
[y
][x
]=-1; /* fill with "invalid" */
493 /* cover all cells of cave */
494 for (y
=0; y
<game
->cave
->h
; y
++)
495 for (x
=0; x
<game
->cave
->w
; x
++)
496 game
->cave
->map
[y
][x
] |= COVERED
;
498 /* to play cover sound */
499 gd_cave_clear_sounds(game
->cave
);
500 gd_sound_play(game
->cave
, GD_S_COVER
);
501 gd_sound_play_cave(game
->cave
);
503 counter_next
=game
->state_counter
+1;
504 /* very important: tell the caller that we loaded a new cave. */
505 /* size of the cave might be new, colors might be new, and so on. */
506 return_state
=GD_GAME_CAVE_LOADED
;
509 /* uncover animation */
510 if (game
->state_counter
<GAME_INT_UNCOVER_ALL
) {
511 counter_next
=game
->state_counter
;
515 /* original game uncovered one cell per line each frame.
516 * we have different cave sizes, so uncover width*height/40 random cells each frame. (original was width=40).
517 * this way the uncovering is the same speed also for intermissions. */
518 for (j
=0; j
<game
->cave
->w
*game
->cave
->h
/40; j
++)
519 game
->cave
->map
[g_random_int_range(0, game
->cave
->h
)][g_random_int_range(0, game
->cave
->w
)] &= ~COVERED
;
521 counter_next
++; /* as we did something, advance the counter. */
523 return_state
=GD_GAME_NOTHING
;
526 /* time to uncover the whole cave. */
527 if (game
->state_counter
==GAME_INT_UNCOVER_ALL
) {
528 for (y
=0; y
<game
->cave
->h
; y
++)
529 for (x
=0; x
<game
->cave
->w
; x
++)
530 game
->cave
->map
[y
][x
] &= ~COVERED
;
532 /* to stop uncover sound. */
533 gd_cave_clear_sounds(game
->cave
);
534 gd_sound_play_cave(game
->cave
);
536 counter_next
=GAME_INT_CAVE_RUNNING
;
537 return_state
=GD_GAME_NOTHING
;
541 if (game
->state_counter
==GAME_INT_CAVE_RUNNING
) {
545 cavespeed
=game
->cave
->speed
; /* cave speed in ms, like 175ms/frame */
547 cavespeed
=40; /* if fast forward, ignore cave speed, and go as 25 iterations/sec */
549 /* ITERATION - cave is running. */
550 return_state
=GD_GAME_NOTHING
; /* normally nothing happes. but if we iterate, this might change. */
551 if (allow_iterate
) /* if allowing cave movements, add elapsed time to timer. and then we can check what to do. */
552 game
->milliseconds_game
+=millisecs_elapsed
;
553 if (game
->milliseconds_game
>=cavespeed
) {
556 game
->milliseconds_game
-=cavespeed
;
557 pl
=game
->cave
->player_state
;
558 iterate_cave(game
, player_move
, fire
, suicide
, restart
);
559 return_state
=GD_GAME_LABELS_CHANGED
; /* as we iterated, the score and the like could have been changed. */
560 if (pl
!=GD_PL_TIMEOUT
&& game
->cave
->player_state
==GD_PL_TIMEOUT
)
561 return_state
=GD_GAME_TIMEOUT_NOW
; /* and if the cave timeouted at this moment, that is a special case. */
564 counter_next
=game
->state_counter
; /* do not change counter state, as it is set by iterate_cave() */
566 /* before covering, we check for time bonus score */
568 if (game
->state_counter
==GAME_INT_CHECK_BONUS_TIME
) {
570 /* if time remaining, bonus points are added. do not start animation yet. */
571 if (game
->cave
->time
>0) {
572 game
->cave
->time
-=game
->cave
->timing_factor
; /* subtract number of "milliseconds" - nothing to do with gameplay->millisecs! */
573 increment_score(game
, game
->cave
->timevalue
); /* higher levels get more bonus points per second remained */
574 if (game
->cave
->time
>60*game
->cave
->timing_factor
) { /* if much time (>60s) remained, fast counter :) */
575 game
->cave
->time
-=8*game
->cave
->timing_factor
; /* decrement by nine each frame, so it also looks like a fast counter. 9 is 8+1! */
576 increment_score(game
, game
->cave
->timevalue
*8);
579 /* just to be neat */
580 if (game
->cave
->time
<0)
582 counter_next
=game
->state_counter
; /* do not change yet */
585 /* if no more points, start waiting a bit, and later start covering. */
586 counter_next
=GAME_INT_WAIT_BEFORE_COVER
;
588 /* play bonus sound */
589 gd_cave_set_seconds_sound(game
->cave
);
590 gd_sound_play_cave(game
->cave
);
591 return_state
=GD_GAME_LABELS_CHANGED
;
594 return_state
=GD_GAME_NOTHING
;
595 counter_next
=game
->state_counter
; /* do not change counter state, as it is set by iterate_cave() */
599 /* after adding bonus points, we wait some time before starting to cover. this is the FIRST frame... so we check for game over and maybe jump there */
600 /* if no more lives, game is over. */
601 if (game
->state_counter
==GAME_INT_WAIT_BEFORE_COVER
) {
602 counter_next
=game
->state_counter
;
604 counter_next
++; /* 40ms elapsed, advance counter */
605 if (game
->type
==GD_GAMETYPE_NORMAL
&& game
->player_lives
==0)
606 return_state
=GD_GAME_NO_MORE_LIVES
;
608 return_state
=GD_GAME_NOTHING
;
611 /* after adding bonus points, we wait some time before starting to cover. ... and the other frames. */
612 if (game
->state_counter
>GAME_INT_WAIT_BEFORE_COVER
&& game
->state_counter
<GAME_INT_COVER_START
) {
613 counter_next
=game
->state_counter
;
615 counter_next
++; /* 40ms elapsed, advance counter */
616 return_state
=GD_GAME_NOTHING
;
619 /* starting to cover. start cover sound. */
620 if (game
->state_counter
==GAME_INT_COVER_START
) {
622 gd_cave_clear_sounds(game
->cave
);
623 gd_sound_play(game
->cave
, GD_S_COVER
);
624 /* to play cover sound */
625 gd_sound_play_cave(game
->cave
);
627 counter_next
=game
->state_counter
+1;
628 return_state
=GD_GAME_NOTHING
;
632 if (game
->state_counter
>GAME_INT_COVER_START
&& game
->state_counter
<GAME_INT_COVER_ALL
) {
633 counter_next
=game
->state_counter
;
637 counter_next
++; /* 40ms elapsed, doing cover: advance counter */
638 /* covering eight times faster than uncovering. */
639 for (j
=0; j
< game
->cave
->w
*game
->cave
->h
*8/40; j
++)
640 game
->cave
->map
[g_random_int_range (0, game
->cave
->h
)][g_random_int_range (0, game
->cave
->w
)] |= COVERED
;
643 return_state
=GD_GAME_NOTHING
;
646 if (game
->state_counter
==GAME_INT_COVER_ALL
) {
648 for (y
=0; y
<game
->cave
->h
; y
++)
649 for (x
=0; x
<game
->cave
->w
; x
++)
650 game
->cave
->map
[y
][x
] |= COVERED
;
652 counter_next
=game
->state_counter
+1;
653 return_state
=GD_GAME_NOTHING
;
658 /* if this is a normal game: */
659 if (game
->type
==GD_GAMETYPE_NORMAL
) {
660 if (game
->cave
->player_state
==GD_PL_EXITED
)
661 cave_finished_highscore(game
); /* we also have added points for remaining time -> now check for highscore */
662 if (game
->player_lives
!=0)
663 return_state
=GD_GAME_NOTHING
; /* and go to next level */
665 return_state
=GD_GAME_GAME_OVER
;
668 /* for snapshots and replays and the like, this is the end. */
669 return_state
=GD_GAME_STOP
;
671 /* load next cave on next call. */
672 counter_next
=GAME_INT_LOAD_CAVE
;
674 g_assert(counter_next
!=GAME_INT_INVALID
);
675 g_assert(return_state
!=GD_GAME_INVALID_STATE
);
679 if (game
->bonus_life_flash
) /* bonus life - frames */
680 game
->bonus_life_flash
--;
681 game
->animcycle
=(game
->animcycle
+1)%8;
684 /* always render the cave to the gfx buffer; however it may do nothing if animcycle was not changed. */
685 if (game
->gfx_buffer
)
686 gd_drawcave_game(game
->cave
, game
->gfx_buffer
, game
->bonus_life_flash
!=0, yellowish_draw
, game
->animcycle
, gd_no_invisible_outbox
);
688 game
->state_counter
=counter_next
;