#include <allegro.h>

#define MAX_MOVES 1000

int t1,t2,t3,fps,fts,speed,paus,lod;
/* t1 is the interrupt driven timer, t2 is the input timer and t3 is the world timer
   fps = frames per second, fts = frames this second */

  BITMAP *buf;
  int px,py;

typedef struct
{
  char left,right,up,down;
} Move;
Move moves[MAX_MOVES];

static void timer_click()
{ t1++; }
END_OF_FUNCTION(timer_click);

void get_input()
{
  Move *m;
  m=&moves[t2%MAX_MOVES];
  poll_joystick();
  poll_keyboard();
  m->left =key[KEY_LEFT] || (num_joysticks && joy[0].stick[0].axis[0].d1);
  m->right=key[KEY_RIGHT]|| (num_joysticks && joy[0].stick[0].axis[0].d2);
  m->up   =key[KEY_UP]   || (num_joysticks && joy[0].stick[0].axis[1].d1);
  m->down =key[KEY_DOWN] || (num_joysticks && joy[0].stick[0].axis[1].d2);
  t2++;
}

void input_callback()
{
  while(t2<t1) get_input();
}

void run()
{
  Move *m;

  while (t2<=t3) get_input();

  m=&moves[t3%MAX_MOVES];
  if (m->left) px--;
  if (m->right)px++;
  if (m->up)   py--;
  if (m->down) py++;
}

void draw()
{
  int black,white,green,red,blue,j;
  black=makecol(0,0,0);
  white=makecol(255,255,255);
  green=makecol(0,255,0);
  blue=makecol(90,90,255);
  red=makecol(255,90,90);

  for (j=0;j<lod;j++) {
    if (key_shifts & KB_CAPSLOCK_FLAG)
      input_callback();
    clear_to_color(buf,black);
  }
//  for (j=(30+t1/3)%50;j<SCREEN_W;j+=50)
//    vline(buf,j,0,SCREEN_H-1,red);
  for (j=35;j<SCREEN_W;j+=50)
    vline(buf,j,0,SCREEN_H-1,blue);
//  for (j=(t1/4)%50;j<SCREEN_H;j+=50)
//    hline(buf,0,j,SCREEN_W-1,red);
  for (j=35;j<SCREEN_H;j+=50)
    hline(buf,0,j,SCREEN_W-1,blue);

  circlefill(buf,px,py,30,green);
  if (paus)
    textprintf_centre_ex(buf,font,SCREEN_W/2,0,white,-1, "(Paused)");
  else
    textprintf_centre_ex(buf,font,SCREEN_W/2,0,white,-1, "Speed=%3d    FPS=%3d ", speed,fps);
  textprintf_centre_ex(buf,font,SCREEN_W/2,10,white,-1, "X=%3d  Y=%3d  T=%4d  LoD=%2d", px,py,t3,lod);
  textprintf_centre_ex(buf,font,SCREEN_W/2,20,white,-1, "Input feature is %s (CapsLock toggles)", key_shifts & KB_CAPSLOCK_FLAG ? "ON ":"OFF");
  textout_centre_ex(buf,font,"Arrows/joystick move circle, P pauses",SCREEN_W/2,30,white,-1);
  textout_centre_ex(buf,font,"+/- change speed, PgUp/PgDn change LoD",SCREEN_W/2,40,white,-1);
  blit(buf,screen,0,0,0,0,SCREEN_W,SCREEN_H);
}

/* This is taken from an Allegro example */
void choose_gfx_mode()
{
  int c,h,w,bpp;
   /* set the graphics mode */
   if (set_gfx_mode(GFX_SAFE, 320, 200, 0, 0)) {
      set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
      allegro_message("Unable to set any graphic mode\n%s\n", allegro_error);
      exit(1);
   }
   set_palette(desktop_palette);

   c = GFX_AUTODETECT;
   w = SCREEN_W;
   h = SCREEN_H;
   bpp = bitmap_color_depth(screen);
   if (!gfx_mode_select_ex(&c, &w, &h, &bpp)) {
      allegro_exit();
      exit(1);
   }

   set_color_depth(bpp);

   if (set_gfx_mode(c, w, h, 0, 0)) {
      set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
      allegro_message("Error setting graphics mode\n%s\n", allegro_error);
      exit(1);
   }
}

int main()
{
  int k;

  allegro_init();
  install_keyboard();
  install_mouse();
  install_timer();
  install_joystick(JOY_TYPE_AUTODETECT);

  LOCK_FUNCTION(timer_click);
  LOCK_VARIABLE(t1);

  choose_gfx_mode();

  t1=1;t2=t3=0;
  paus=0;lod=1;
  px=SCREEN_W/2; py=SCREEN_H/2+40;
  speed=50;
  install_int_ex(timer_click,BPS_TO_TIMER(speed));

  buf=create_bitmap(SCREEN_W,SCREEN_H);

  while (!key[KEY_ESC]) {

    if (paus && keypressed()) {
      paus=0;
      install_int_ex(timer_click,BPS_TO_TIMER(speed));
    }
    if (t1>t3) {

      run();
      t3++;
      while (keypressed()) {
        k=readkey()>>8;
        if (k==KEY_P) {
          paus=1;
          install_int_ex(timer_click,0);
        }
        switch(k) {
          case KEY_MINUS: if (speed>2) speed--;
            install_int_ex(timer_click,BPS_TO_TIMER(speed));
            break;
          case KEY_EQUALS: if (speed<200) speed++;
            install_int_ex(timer_click,BPS_TO_TIMER(speed));
            break;
          case KEY_PGDN: if (lod>1) lod--;
            break;
          case KEY_PGUP: if (lod<200) lod++;
            break;
        }
      }
      if (!(t3%speed)) {
        fps=fts; fts=0;
      }

    } else {

      draw();
      fts++;
    }
  }
  destroy_bitmap(buf);
  return 0;
}
END_OF_MAIN();

