#include "main.h"
#include "setup.h"
#include "timer.h"
#include "ex.h"
#include "pixmap.h"
#include "cosmo.h"
#include "animation.h"
#include "digit.h"

/* 1 ブロック落すのに何コマ使えるか計算 */
double set_wait(double swait)
{
  for(t=SIZE;(1.0/ALRM_PAR_SEC)*t>swait && t>1;t/=2);

  swait/=t;
  t=SIZE/t;

  return swait;
}

/* ボールが来る間隔 */
void set_ball()
{
       if(user.level< 10) ball=5;
  else if(user.level< 50) ball=6;
  else if(user.level<100) ball=6;
  else if(user.level<120) ball=7;
  else ball=8;
}  

/* ブロックが落ちるスピード */
void calc_wait()
{
       if(user.level< 10) wait3=2.0-0.1*user.level;
  else if(user.level< 50) wait3=1.5-0.0325*(user.level-10);
  else if(user.level< 99) wait3=0.8-0.016*(user.level-50);
  else if(user.level==99) wait3=0.0;
  else if(user.level<110) wait3=0.04-0.004*(user.level-100);
  else wait3=0.0;
}

/* レベルに合わせて next のブロック塊を作成 */
void mk_next_block()
{
       if(user.level< 20)
  {
    nblock[0]=((random()% 2)>0 ? BLOCK : COSMO);
    nblock[1]=((random()% 2)>0 ? BLOCK : COSMO);
    nblock[2]=((random()% 2)>0 ? BLOCK : COSMO);
  }
  else if(user.level< 50)
  {
    nblock[0]=((random()% 5)>2 ? BLOCK : COSMO);
    nblock[1]=((random()% 5)>2 ? BLOCK : COSMO);
    nblock[2]=((random()% 5)>2 ? BLOCK : COSMO);
  }
  else if(user.level<100)
  {
    nblock[0]=((random()% 7)>3 ? BLOCK : COSMO);
    nblock[1]=((random()% 7)>3 ? BLOCK : COSMO);
    nblock[2]=((random()% 7)>3 ? BLOCK : COSMO);
  }
  else if(user.level<130)
  {
    nblock[0]=((random()%12)>6 ? BLOCK : COSMO);
    nblock[1]=((random()%12)>6 ? BLOCK : COSMO);
    nblock[2]=((random()%12)>6 ? BLOCK : COSMO);
  }
  else
  {
    nblock[0]=((random()%11)>6 ? BLOCK : COSMO);
    nblock[1]=((random()%11)>6 ? BLOCK : COSMO);
    nblock[2]=((random()%11)>6 ? BLOCK : COSMO);
  }
}

/* level up! */
#define level_up()\
{\
  user.level++;\
  put_level(user.level);\
}

/* level Bonus */
void level_bonus(int f)
{
  static int bonusf=0;

  if(f==1) { bonusf=0; return; }   /* 初期化 */
  if(bonusf!=0) return;
  if(s_level== 10 && user.level>= 20)
  {
    bonusf=1;
    entry_score(SIZE*3,(HEIGHT-1)/2*SIZE, 100000,1);
  }
  if(s_level== 50 && user.level>= 60)
  {
    bonusf=1;
    entry_score(SIZE*3,(HEIGHT-1)/2*SIZE, 500000,1);
  }
  if(s_level==100 && user.level>=110)
  {
    bonusf=1;
    entry_score(SIZE*3,(HEIGHT-1)/2*SIZE,1000000,1);
  }

  while(animation()) nap(1);
}

void init_values(int level)
{
  int i,j;

/* スコア等を初期化 */
  user.level=level;
  user.score=0;
  user.line=0;
  user.cosmo=0;
  level_bonus(1);

/* 諸々 */
  qp_f=0;
  s_level=level;
  loopf=0;
  set_ball();
  star=128;
  ballc=ball;
  starc=star;
  starf=0;
  nblock[0]=-1;
  wait3=2.0;
  put_level(user.level);

/* ゲーム画面用バッファ(?)を初期化 */
  for(j=0;j<HEIGHT+1;j++)
  {
    c_buf[0][j]=c_buf[7][j]=WALL;
    for(i=1;i<=6;i++)
    {
      c_buf[i][j]=(j<HEIGHT ? NONE : WALL);
    }
  }

/* animation の初期化 */
  init_animation();
}

/* 特定のブロックを探す */
int search(int c,int *x,int *y)
{
  int ax,ay;

  for(ay=0;ay<HEIGHT;ay++)
  {
    for(ax=1;ax<=6;ax++)
    {
      if( c_buf[ax][ay]==c ) break;
    }
    if(ax<=6) break;
  }

  if(ax>6) return 0;

  if(x) *x=ax;
  if(y) *y=ay;
  return 1;
}

/* ブロックを描画 */
void put_block()
{
  if(tb[0]!=-1)
  {
    return_back(tb[0]);
    return_back(tb[1]);
    return_back(tb[2]);
  }

  tb[0]=put_sp(mwin,block[0],bx+xpos[di][0],by+ypos[di][0],0);
  tb[1]=put_sp(mwin,block[1],bx+xpos[di][1],by+ypos[di][1],0);
  tb[2]=put_sp(mwin,block[2],bx+xpos[di][2],by+ypos[di][2],0);
}

/* 揃ったラインを消す */
void delete_line(int t)
{
  int i,j,f=0,l=0;

  for(j=0;j<HEIGHT;j++)
  {
    for(i=1;i<=6;i++) if(c_buf[i][j]!=BLOCK) break;
    if(i<=6) continue;

    f++; l+=(j-1)*SIZE-SIZE/2;
    user.line++;
    for(i=1;i<=6;i++)
    {
      c_buf[i][j]=NONE;
      return_back(c_tmp[i][j]);
    }
  }

  x_flush();
  put_line(user.line);

  if(f>0)
  {
    l/=f;
    entry_score(SIZE*3,l,f*500,t*f/2+1);
    while(animation()) nap(1);
  }

  nap(ALRM_PAR_SEC/3);

  if( f>0 && (user.line%3)==0 ) level_up();
}

static int sgcols[16] = {
  Blue1 ,Blue2 ,Blue3 ,Blue4 ,
  Blue5 ,Blue6 ,Blue7 ,Blue8 ,
  Blue9 ,Blue10,Blue11,Blue12,
  Blue13,Blue14,Blue15,Blue16
};

/* star のゲージを塗る */
void add_sg(int n)
{
  int c;

  if(n%2!=0) return;
  n=(128-n)/2;
  c=(n*15)/64;
  n++;

  set_col(sgcols[c]);

       if(n<23)
  {
    XDrawLine(disp,sgwattr.pix,gc,n,44,n,64);
    XDrawLine(disp,sgwattr.win,gc,n,44,n,64);
  }
  else if(n<45)
  {
    XDrawLine(disp,sgwattr.pix,gc,n,43-(n-23),n,63-(n-23));
    XDrawLine(disp,sgwattr.win,gc,n,43-(n-23),n,63-(n-23));
  }
  else
  {
    XDrawLine(disp,sgwattr.pix,gc,n,21,n,41);
    XDrawLine(disp,sgwattr.win,gc,n,21,n,41);
  }

  if(n==65)
  {

    XCopyArea(disp,mask ,sgwattr.pix,and_gc,
	      sp[STAR].x,sp[STAR].y,
	      sp[STAR].width,sp[STAR].height,
	      1,1);
    XCopyArea(disp,chara,sgwattr.pix, or_gc,
	      sp[STAR].x,sp[STAR].y,
	      sp[STAR].width,sp[STAR].height,
	      1,1);
    XCopyArea(disp,sgwattr.pix,sgwattr.win,gc,
	      1,1,sp[STAR].width,sp[STAR].height,1,1);
  }
}

/* ボールを転がす */
void manage_ball()
{
  int ball_ax,ball_ay;
  int ball_bx,ball_by;
  int tmpid;
  signed int ball_di=1;
  int rev=0;
  int cosmo_di;
  int killc=0,t;
  int i;

  set_ball();
  ballc=ball;

/* ボールを探す */
  if( search(BALL_L,&ball_ax,&ball_ay) ) ball_di=-1;
  else { search(BALL_R,&ball_ax,&ball_ay); ball_di=1; }

  c_buf[ball_ax][ball_ay]=NONE;
  tmpid=c_tmp[ball_ax][ball_ay];
  ball_bx=(ball_ax-1)*SIZE;
  ball_by=ball_ay*SIZE-SIZE-SIZE/2;
  entry_ball(ball_bx,ball_by,tmpid);

/* cosmo を跳ね飛ばす */
  for(;;)
  {
    if( c_buf[ball_ax][ball_ay+1]==COSMO || c_buf[ball_ax][ball_ay+1]==NONE )
    {
      ball_ay++;
      chdir_ball(DOWN);
      entry_curtain(ball_bx,ball_by,2);
      ball_by+=SIZE;

      rev=0;
      cosmo_di=1-ball_ax/4;
    }
    else
    {
      for(i=0;i<2;i++)
      {
	if( c_buf[ball_ax+ball_di][ball_ay]==BLOCK ||
	    c_buf[ball_ax+ball_di][ball_ay]==WALL )
	{
	  /* 壁で跳ね返る */
	  rev++;
	  ball_di=-ball_di;
	}
      }

      if(rev==2) break;	/* 同じラインで２回跳ね返ったら終り */

      ball_ax+=ball_di;
      chdir_ball((ball_di==1 ? RIGHT : LEFT));
      entry_curtain(ball_bx,ball_by,4);
      ball_bx+=ball_di*SIZE;
      cosmo_di=(ball_di+2)/2;
    }

    if( c_buf[ball_ax][ball_ay]==COSMO )
    {
      killc++;
      user.cosmo++;
      put_kill_cosmo(user.cosmo);
      if( (user.cosmo%30)==0 ) level_up();
      if(starc>0) { starc--; add_sg(starc); }
      entry_cosmo((ball_ax-1)*SIZE,ball_ay*SIZE-SIZE-SIZE/2,
		  c_tmp[ball_ax][ball_ay],cosmo_di);
      c_buf[ball_ax][ball_ay]=NONE;
    }

    for(i=0;i<SIZE;i+=SIZE/4*rough) { animation(); nap(1); }
  }

  delete_ball();
  entry_pa(ball_bx,ball_by);
  entry_curtain(ball_bx,ball_by,4);

  if(killc>0)
  {
    t=(killc/6+1);
    if(!search(COSMO,NULL,NULL) && killc>=6) t*=2;
    entry_score(ball_bx+SIZE/2,ball_by,killc*200,t);
  }

  while(animation()) nap(1);

  x_flush();
  nap(ALRM_PAR_SEC/3);
}

/* ☆彡 */
void manage_star()
{
  int i,j;
  int star_ax,star_ay;
  int star_bx,star_by;
  int sx,sy;
  int killc=0,t;

  starf=0;
  starc=star;
  ballc=ball;

/* ☆を探す */
  search(STAR,&star_ax,&star_ay);

  return_back(c_tmp[star_ax][star_ay]);
  c_buf[star_ax][star_ay]=NONE;
  star_bx=0;
  sx=star_ax*SIZE-SIZE/2;
  sy=star_by=star_ay*SIZE-SIZE/2;

/* カーテンを降ろす */
  for(i=1;i<=7 && star_ay+i<HEIGHT;i++)
  {
    star_bx=0;

    for(j=1;j<=6;j++)
    {
      entry_curtain(star_bx,star_by,2);
      star_bx+=SIZE;
    }

    for(j=0;j<8;j+=rough) { animation(); nap(1); }

    star_bx=0;
    for(j=1;j<=6;j++)
    {
      if(c_buf[j][star_ay+i]==COSMO)
      {
	return_back(c_tmp[j][star_ay+i]);
	c_tmp[j][star_ay+i]=
	  put_sp(mwin,COSMO1,star_bx,star_by,0);
      }
      star_bx+=SIZE;
    }

    star_by+=SIZE;
  }

  while(animation()) nap(1);

  x_flush();
  nap(ALRM_PAR_SEC/3);

/* cosmo を潰す */
  star_by=star_ay*SIZE-SIZE/2;
  for(i=1;i<=7 && star_ay+i<HEIGHT;i++)
  {
    star_bx=0;
    for(j=1;j<=6;j++)
    {
      if(c_buf[j][star_ay+i]==COSMO)
      {
	killc++;
	c_buf[j][star_ay+i]=NONE;
	entry_cosmo_p(star_bx,star_by,c_tmp[j][star_ay+i]);
      }
      star_bx+=SIZE;
    }
    star_by+=SIZE;
  }

  while(animation()) nap(1);

  if(killc>0)
  {
    t=(killc/6+1);
    if(!search(COSMO,NULL,NULL) && killc>=6) t*=2;
    entry_score(sx,sy,killc*200,t);
  }
  while(animation()) nap(1);
  user.cosmo+=killc;
  put_kill_cosmo(user.cosmo);
  if( (user.cosmo%30)==0 ) level_up();

  x_flush();
  nap(ALRM_PAR_SEC/3);

  mk_sgw();
}

/* 浮いているブロックを落す */
void attach_floats()
{
  int i,j;
  int n=0;

  for(;;)
  {
    n=0;
    /* 浮いているブロックを登録 */
    for(j=HEIGHT-2;j>=0;j--)
      for(i=1;i<=6;i++)
	if( c_buf[i][j]!=NONE && c_buf[i][j+1]==NONE )
	{
	  entry_fall((i-1)*SIZE,j*SIZE-SIZE-SIZE/2,c_buf[i][j],
		     c_tmp[i][j],&c_tmp[i][j+1]);
	  c_buf[i][j+1]=c_buf[i][j];
	  c_buf[i][j]=NONE;
	  n++;
	}

    if(n==0) break;

    /* 一斉に落す */
    while(animation()) nap(1);
  }
}

/* 全消し */
void zenkeshi()
{
  entry_score(SIZE*3,(HEIGHT-1)/2*SIZE,2000*user.level,1);
  while(animation()) nap(1);
}

/* ブロック着地後の処理 */
void manage_attach()
{
  int i;

  for(i=0;i<3;i++)
  {
    if(block[i]==None) continue;
    c_buf[ax+xpos[di][i]/SIZE][ay+ypos[di][i]/SIZE]=block[i];
    c_tmp[ax+xpos[di][i]/SIZE][ay+ypos[di][i]/SIZE]=tb[i];
  }

  attach_floats();
  delete_line(1);
  attach_floats();

  if(starf)
  {
    manage_star();
    attach_floats();
    delete_line(2);
    attach_floats();
  }

  if(!ballc)
  {
    manage_ball();
    attach_floats();
    delete_line(2);
    attach_floats();
  }

  if(!search(COSMO,NULL,NULL) && !search(BLOCK,NULL,NULL)) zenkeshi();
}

#define add_fall_scr()\
if(key==keys.drop || (key==keys.fall && event.type==KeyPress))\
{\
  user.score+=user.level/10;\
  put_scr(user.score);\
}

/* ブロックを１コマ落す */
int down_block()
{
  if( (by+SIZE/2)%SIZE != 0 )
  {
    if( (by+t+SIZE+SIZE/2-1)/SIZE > (by+SIZE+SIZE/2-1)/SIZE )
      by=ay*SIZE-SIZE-SIZE/2;
    else by+=t;

    w=0.0;
    add_fall_scr();
  }
  else if( movable_check(DOWN) )
  {
    ay++;
    by=ay*SIZE-SIZE*2-SIZE/2+t;
    w=0.0;
    if( (by+SIZE/2)%SIZE == 0) add_fall_scr();
  }
  else
  {
    add_fall_scr();
    manage_attach();
    init_block();
    return 1;
  }

  put_block();
  return 0;
}  

/* ブロックを左右へ動かす */
void move_block(int d)
{
  if(movable_check(d))
  {
    switch(d)
    {
      case LEFT:  bx-=SIZE; break;
      case RIGHT: bx+=SIZE; break;
    }

    ax=bx/SIZE+1;
    put_block();
  }
}

/* ブロックを回転させる */
void rotate_block()
{
  if(starf) return;
  if( c_buf[ ax+xcrot[di] ][ ay+ycrot[di] ] == NONE )
  {
    return_back(tb[0]);

    if( block[0]!=block[1] )
      return_back(tb[1]);

    if( block[1]!=block[2] )
      return_back(tb[2]);

    di++; di&=0x3;

    if( block[0]!=block[1] )
      tb[0]=put_sp(mwin, block[0],bx+xpos[di][0],by+ypos[di][0],0);
    else
      tb[0]=tb[1];

    if( block[1]!=block[2] )
      tb[1]=put_sp(mwin, block[1],bx+xpos[di][1],by+ypos[di][1],0);
    else
      tb[1]=tb[2];

    tb[2]=put_sp(mwin, block[2],bx+xpos[di][2],by+ypos[di][2],0);
  }
}

/* ブロックが着地する瞬間は時間を長くする */
void extend_time()
{
  if( (by+SIZE/2)%SIZE ) return;
  if( movable_check(DOWN) )
  {
    if(wait1!=wait2) wait1=set_wait(wait3);
  }
  else
  {
    wait1=set_wait(1.0);
    wait1*=(SIZE/t);
    if(wait1==wait2) wait1+=0.001;
  }
}

/* ブロックを下に落す */
void drop_block()
{
  w+=1.0/ALRM_PAR_SEC;
  if(w<wait1) return;

  w=0.0;
  down_block();
  extend_time();
}

/* star を使わない (ボーナスにする) */
void get_star()
{
  if(starf==0) return;

  return_back(tb[0]);
       if(user.level< 10) entry_score(bx,by,  50000,1);
  else if(user.level< 50) entry_score(bx,by,  80000,1);
  else if(user.level<100) entry_score(bx,by, 100000,1);
  else                    entry_score(bx,by, 200000,1);

  while(animation()) nap(1);

  mk_sgw();

  starf=0;
  starc=star;
  ballc=ball;

  init_block();
}

/* ゲーム中だけど本当に quit する？ */
int quit_session()
{
  int tmpid;
  int d=0;

  if(loopf<0) return 0;

  XCopyArea(disp,mwin,mwintmp,gc,0,0,w2attr.width,w2attr.height,0,0);

  mk_mwin();
  set_font(FNT24);
  set_col(White);
  XDrawString(disp,mwin,gc,
	      SIZE*3-x_get_word_width(FNT24,"Really Quit?")/2,SIZE*5-SIZE/2-6,
	      "Really Quit?",12);

  set_font(FNT14);
  set_col(Yes);
  XDrawString(disp,mwin,gc,SIZE*2+4,7*SIZE-SIZE/2-10,"No, Continue",12);
  set_col(No);
  XDrawString(disp,mwin,gc,SIZE*2+4,8*SIZE-SIZE/2-10,"Yes, Quit",9);
  minx=miny=0;
  maxx=w2attr.width; maxy=w2attr.height;
  tmpid=put_sp(mwin,COSMO,SIZE,(d+6)*SIZE-SIZE/2,0);
  x_flush();

  for(;;)
  {
    get_event(1);
    if(event.type!=KeyPress) continue;
    return_back(tmpid);

    if(key==keys.up || key==keys.down ) d=1-d;
    if(key==keys.yes) { d=1; break; }
    if(key==keys.no) { d=0; break; }
    if(key==keys.decide) break;

    tmpid=put_sp(mwin,COSMO,SIZE,(d+6)*SIZE-SIZE/2,0);
    x_flush();
  }

  while(get_event(0)||key!=0);

  XCopyArea(disp,mwintmp,mwin,gc,0,0,w2attr.width,w2attr.height,0,0);
  minx=miny=0;
  maxx=w2attr.width; maxy=w2attr.height;
  x_flush();

  if(d==1) return LOOP_QUIT;
      else return 0;
}

/* pause */
void pause_session()
{
  if(loopf<0) return;

  XCopyArea(disp,mwin,mwintmp,gc,0,0,w2attr.width,w2attr.height,0,0);

  mk_mwin();
  set_font(FNT24);
  set_col(Pause);
  XDrawString(disp,mwin,gc,
	      SIZE*3-x_get_word_width(FNT24,"PAUSE!")/2,SIZE*7-SIZE/2-6,
	      "PAUSE!",6);
  minx=miny=0;
  maxx=w2attr.width; maxy=w2attr.height;
  x_flush();

#ifdef USE_PAD
  clear_pad_buffer();
#endif
  while(event.type!=KeyPress || key==keys.pause) get_event(1);
  while(get_event(0)||key!=0);

  XCopyArea(disp,mwintmp,mwin,gc,0,0,w2attr.width,w2attr.height,0,0);
  minx=miny=0;
  maxx=w2attr.width; maxy=w2attr.height;
  x_flush();
}

/* 入力された動作を実行 */
void manage()
{
  int bt,ret;
  int i;

/* 過去 (sleep 中) に押された */
  if(qp_f==keys.quit ) { loopf=quit_session(); qp_f=0; }
  if(qp_f==keys.pause) { pause_session(); qp_f=0; }

/* 押している間作動 */
  if(key==keys.drop)
  {
    for(i=0;i<rough;i++)
    {
      bt=t;
      t=SIZE;
      ret=down_block();
      t=bt;
      extend_time();
      if(ret==1) break;
      x_flush();
    }
  }

  if(event.type!=KeyPress) return;

/* 押した瞬間のみ作動 */
  if(key==keys.fall ) { bt=t; t=SIZE; down_block(); t=bt; extend_time(); }
  if(key==keys.right) { move_block(RIGHT); extend_time(); }
  if(key==keys.left ) { move_block(LEFT);  extend_time(); }
  if(key==keys.rot  ) { rotate_block();    extend_time(); }
  if(key==keys.star ) { get_star(); extend_time(); }
}

/* next を表示 */
void put_next()
{
  int i;

  for(i=0;i<3;i++)
  {
    if(ntb[i]!=-1) return_back(ntb[i]);
    if(nblock[i]!=NONE)
      ntb[i]=put_sp(nextattr.pix,nblock[i],xpos[0][i],ypos[0][i],0);
    else
      ntb[i]=-1;
  }

  XCopyArea(disp,nextattr.pix,nextattr.win,gc,
	    0,0,nextattr.width,nextattr.height,0,0);
}

/* 落下してくるブロックの初期化 */
void init_block()
{
  int i;

  level_bonus(0);

  if(nblock[0]==-1)
  {
    mk_next_block();
    ntb[0]=ntb[1]=ntb[2]=-1;
  }

  block[0]=nblock[0];
  block[1]=nblock[1];
  block[2]=nblock[2];
  if(block[0]==STAR) starf=1;

  ballc--;
  mk_next_block();

  if(ballc==1) nblock[random()%3]=(random()%2)+BALL_L;
  if(ballc==1 && starc==0)
  {
    nblock[0]=STAR;
    nblock[1]=NONE;
    nblock[2]=NONE;
  }
  put_next();

  ax=3;
  ay=0;
  bx=(ax-1)*SIZE;
  by=ay*SIZE-SIZE-SIZE/2;
  di=0;

  nap(ALRM_PAR_SEC/3);

  tb[0]=-1;
  put_block();
#ifdef USE_PAD
  clear_pad_buffer();
#endif
  while(get_event(0));
  if(key!=0) event.type=KeyPress;

  if(key==keys.left||key==keys.right)
  {
    manage();
    manage();
  }

  if(starf==0)
  {
    for(i=0;i<3;i++)
      if( c_buf[ax+xpos[di][i]/SIZE][ay+ypos[di][i]/SIZE]!=None ) break;
    if(i<3) loopf=GAMEOVER;
  }
  else
    if( c_buf[ax][ay]!=None ) loopf=GAMEOVER;
    
  w=0.0;
  calc_wait();
  wait2=set_wait(wait3);
  wait1=wait2+1.0;

  x_flush();
}

/* あるキャラクタの白黒のやつを検索 */
int get_bw(int id)
{
  switch(id)
  {
    case COSMO:  return COSMO5;
    case BLOCK:  return BLOCK_BW;
    case BALL_L: return BALL_L_BW;
    case BALL_R: return BALL_R_BW;
    case STAR:   return STAR_BW;
  }

  return NONE;
}

/* Game Over */
void gameover()
{
  int i,j;

  for(i=0;i<3;i++) nblock[i]=get_bw(nblock[i]);
  put_next();

  for(i=0;i<3;i++)
  {
    if(block[i]==None) continue;
    c_buf[ax+xpos[di][i]/SIZE][ay+ypos[di][i]/SIZE]=block[i];
    c_tmp[ax+xpos[di][i]/SIZE][ay+ypos[di][i]/SIZE]=tb[i];
  }

  for(j=HEIGHT-1;j>0;j--)
  {
    for(i=1;i<=6;i++)
    {
      if(c_buf[i][j]!=NONE)
      {
	return_back(c_tmp[i][j]);
	put_sp(mwin,get_bw(c_buf[i][j]),(i-1)*SIZE,(j-1)*SIZE-SIZE/2,0);
      }
    }

    x_flush();
    nap((3-rough)*3);
  }

  set_font(FNT24);
  set_col(Gameover);
  XDrawString(disp,mwin,gc,
	      SIZE*3-x_get_word_width(FNT24,"GAME OVER")/2,SIZE*7-20,
	      "GAME OVER",9);
  minx=0; maxx=SIZE*6;
  miny=SIZE*7-20-30; maxy=SIZE*7;
  x_flush();

#ifdef USE_PAD
  clear_pad_buffer();
#endif
  while(get_event(0)||key!=0);
  while(event.type!=KeyPress) get_event(1);
}

/* メインループ */
int main_loop(int level)
{
  mk_game_window();
  init_values(level);
  fflush(stdout);

  init_block();
  wait1=wait2;
  while(!loopf)
  {
    get_event(0);
    manage();
    drop_block();
    x_flush();
    if(wait1>0.0 && key!=keys.drop) nap(1);
  }

  if(loopf==GAMEOVER) gameover();
  loopf=-1;

  return 0;
}
