/**********************************************/
/* Multi-purpose game logic and update code   */
/* Evert Glebbeek 2002                        */
/* eglebbk@phys.uva.nl                        */
/**********************************************/
#include <allegro.h>
#include <string.h>
#include "playgame.h"

volatile unsigned int global_cycles_passed;
static unsigned int cycles_counted = 0;

/* This flag becomes TRUE when the playgame() loop should end */
static int game_done = FALSE;

/* Screen update flag */
static int screen_changed = TRUE;

/* Timer/synchronization routine */
static void inc_game_counter(void)
{
   global_cycles_passed++;
   cycles_counted++;
}
END_OF_STATIC_FUNCTION(inc_game_counter);

/* Initialize the game-play functions */
void playgame_init(const int gamespeed)
{
   LOCK_FUNCTION(inc_game_counter);
   LOCK_VARIABLE(global_cycles_passed);
   LOCK_VARIABLE(cycles_counted);
   install_int(inc_game_counter, gamespeed);
}

inline void set_game_done(void)
{
   game_done = TRUE;
}

inline void set_screen_changed(void)
{
   screen_changed = TRUE;
}

inline void clear_screen_changed(void)
{
   screen_changed = FALSE;
}

inline void synchronize(void)
{
   cycles_counted = 0;
}

inline void reset_game_timer(void)
{
   cycles_counted = 0;
   global_cycles_passed = 0;
}

void playgame(void)
{
   game_done = FALSE;
   screen_changed = TRUE;

   playgame_preamble();

   reset_game_timer();

   TRACE("Start playgame-loop\n");
   do {
      /* Game state update preamble */
      game_gfx_update_preamble();

      /* Graphical update */
      if (screen_changed) {
         game_gfx_update();
         clear_screen_changed();
      } else {
         game_gfx_skip();
      }
      
      yield_timeslice();

      /* Update game state */
      while(cycles_counted) {
         game_state_update();
         if (game_done)
            break;
         if (cycles_counted)
            cycles_counted--;
      }

      if (game_done)
         break;

      /* Process user input */
      game_input();
   } while (!game_done);
   TRACE("Playgame-loop ended\n");
   /* And done */
   playgame_closing();
}
