20090122
[gdash.git] / src / gameplay.c
blob468d1d1399e9d4e3eb5735b17fc00c611d2adae8
1 /*
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.
16 #include <glib.h>
17 #include <glib/gi18n.h>
18 #include "cave.h"
19 #include "caveobject.h"
20 #include "cavesound.h"
21 #include "caveset.h"
22 #include "caveengine.h"
23 #include "settings.h"
24 #include "gameplay.h"
25 #include "util.h"
26 #include "sound.h"
27 #include "config.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
46 /* start covering */
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+ */
56 static void
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);
66 void
67 gd_game_free(GdGame *game)
69 /* stop sounds */
70 gd_sound_off();
72 if (game->gfx_buffer)
73 gd_cave_map_free(game->gfx_buffer);
75 game->player_lives=0;
76 if (game->cave)
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) {
81 GList *citer;
83 /* check all caves */
84 for (citer=gd_caveset; citer!=NULL; citer=citer->next) {
85 GdCave *cave=(GdCave *)citer->data;
86 GList *riter;
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 */
99 riter=nextrep;
103 /* free the list of newly recorded replays, as we checked them */
104 g_list_free(game->replays_recorded);
105 game->replays_recorded=NULL;
108 g_free(game);
111 /* add bonus life. if sound enabled, play sound, too. */
112 static void
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)
118 if (inform_user) {
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
133 static void
134 increment_score(GdGame *game, int increment)
136 int i;
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. */
148 static void
149 load_cave(GdGame *game)
151 guint32 seed;
153 /* delete gfx buffer */
154 if (game->gfx_buffer)
155 gd_cave_map_free(game->gfx_buffer);
156 game->gfx_buffer=NULL;
158 /* load the cave */
159 game->cave_score=0;
160 switch (game->type) {
161 case GD_GAMETYPE_NORMAL:
162 /* delete previous cave */
163 gd_cave_free(game->cave);
164 game->cave=NULL;
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);
176 /* create replay */
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);
187 break;
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);
196 break;
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);
203 break;
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);
215 break;
217 case GD_GAMETYPE_CONTINUE_REPLAY:
218 g_assert_not_reached();
219 break;
222 game->milliseconds_anim=0;
223 game->milliseconds_game=0; /* set game timer to zero, too */
227 GdCave *
228 gd_create_snapshot(GdGame *game)
230 GdCave *snapshot;
231 g_return_val_if_fail (game->cave != NULL, NULL);
233 /* make an exact copy */
234 snapshot=gd_cave_new_from_cave(game->cave);
235 return snapshot;
238 /* this starts a new game */
239 GdGame *
240 gd_game_new(const char *player_name, const int cave, const int level)
242 GdGame *game;
244 game=g_new0(GdGame, 1);
246 gd_strcpy(game->player_name, player_name);
247 game->cave_num=cave;
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;
258 return game;
261 /* starts a new snapshot playing */
262 GdGame *
263 gd_game_new_snapshot(GdCave *snapshot)
265 GdGame *game;
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;
279 return game;
282 /* starts a new snapshot playing */
283 GdGame *
284 gd_game_new_test(GdCave *cave, int level)
286 GdGame *game;
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;
300 return game;
303 /* starts a new snapshot playing */
304 GdGame *
305 gd_game_new_replay(GdCave *cave, GdReplay *replay)
307 GdGame *game;
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;
320 return game;
325 /* called from iterate_cave, to increment cave and level number.
326 does not load the cave, just sets the new numbers!
328 static void
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()) {
335 game->cave_num=0;
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) */
339 game->level_num=4;
342 /* show story. */
343 /* if the user fails to solve the cave, the story will not be shown again */
344 game->show_story=TRUE;
351 static void
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) {
366 gboolean result;
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. */
371 if (!result)
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;
378 /* iterate cave */
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);
400 next_level(game);
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 */
411 next_level(game);
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;
417 else
418 game->state_counter=GAME_INT_COVER_START; /* jump immediately to covering */
420 else {
421 /* start cover animation immediately */
422 game->state_counter=GAME_INT_COVER_START;
427 GdGameState
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 */
431 int x, y;
432 GdGameState return_state;
433 int counter_next;
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) {
440 frame=TRUE;
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();
448 else
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. */
451 load_cave(game);
452 return_state=GD_GAME_NOTHING;
453 counter_next=GAME_INT_SHOW_STORY;
455 else
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. */
466 } else {
467 /* if no story */
468 counter_next=GAME_INT_START_UNCOVER;
469 return_state=GD_GAME_NOTHING;
472 else
473 if (game->state_counter==GAME_INT_SHOW_STORY_WAIT) {
474 /* if user presses fire, proceed with loading the cave. */
475 if (fire) {
476 counter_next=GAME_INT_START_UNCOVER;
477 return_state=GD_GAME_NOTHING;
478 } else {
479 /* do nothing. */
480 counter_next=game->state_counter;
481 return_state=GD_GAME_NOTHING;
484 else
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;
508 else
509 /* uncover animation */
510 if (game->state_counter<GAME_INT_UNCOVER_ALL) {
511 counter_next=game->state_counter;
512 if (frame) {
513 int j;
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;
525 else
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;
539 else
540 /* normal. */
541 if (game->state_counter==GAME_INT_CAVE_RUNNING) {
542 int cavespeed;
544 if (!fast_forward)
545 cavespeed=game->cave->speed; /* cave speed in ms, like 175ms/frame */
546 else
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) {
554 GdPlayerState pl;
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 */
567 else
568 if (game->state_counter==GAME_INT_CHECK_BONUS_TIME) {
569 if (frame) {
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)
581 game->cave->time=0;
582 counter_next=game->state_counter; /* do not change yet */
584 else
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;
593 else {
594 return_state=GD_GAME_NOTHING;
595 counter_next=game->state_counter; /* do not change counter state, as it is set by iterate_cave() */
598 else
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;
603 if (frame)
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;
607 else
608 return_state=GD_GAME_NOTHING;
610 else
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;
614 if (frame)
615 counter_next++; /* 40ms elapsed, advance counter */
616 return_state=GD_GAME_NOTHING;
618 else
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;
630 else
631 /* covering. */
632 if (game->state_counter>GAME_INT_COVER_START && game->state_counter<GAME_INT_COVER_ALL) {
633 counter_next=game->state_counter;
634 if (frame) {
635 int j;
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;
645 else
646 if (game->state_counter==GAME_INT_COVER_ALL) {
647 /* 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;
655 else {
656 /* cover all + 1 */
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 */
664 else
665 return_state=GD_GAME_GAME_OVER;
667 else
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);
677 /* draw the cave */
678 if (frame) {
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;
689 return return_state;