/*******************************************************************

  XPUYO   puyo-puyo for X11          (c)1997 CDR/TK  (Tatsuya Kudoh)

  screen.c ---- main screen handling

  メイン画面の制御 (キャラクタ単位)

  x,y : キャラクタ単位の座標。
        最上段(y==0)は使用しない。2段目(y==1)は表示されない。

  col : 1〜6はぷよ、NOTHINGは何もなし、WHITE_PUYOは透明ぷよ

*******************************************************************/

#include<stdio.h>
#include"xpuyo.h"

static int Map_col[8][15];  /* 仮想画面   */

static int Color_target;    /* 消去判定用 */
static int Killed_x[3];
static int Killed_y[3];
static int Killed;



/* 仮想画面を実際の表示にフラッシュする。 */

void refresh( void )
{
  int x,y,col,form,dir;

  for( y = 0 ; y < 15 ; y++ )
    for( x = 0 ; x < 8 ; x++ ){
      switch( Map_col[x][y] ){
      case NOTHING:
	col = 0;
	form = 0;
	break;

      case WALL:
	col = 0;
	form = 1;
	break;

      case WHITE_PUYO:
	col = 0;
	form = 2;
	break;

      default:
	col = Map_col[x][y];
	form = 0;
	for( dir = 0 ; dir < 4 ; dir++ )
	  if( Map_col[x+Dir_x[dir]][y+Dir_y[dir]] == col )
	    form += 1 << dir;
      }

      set_graph(x,y,col,form);
    }
  flush_scr();
}



/* 仮想画面の初期化 */

void init_map( void )
{
  int x,y;

  for( y = 0 ; y < 14 ; y++ ){
    Map_col[0][y] = Map_col[7][y] = WALL;
    for( x = 1 ; x < 7 ; x++ )
      Map_col[x][y] = NOTHING;
  }
  for( x = 0 ; x < 8 ; x++ )
    Map_col[x][14] = WALL;

  refresh();
}



/* 中に浮いているぷよを落す。一つでも落ちたら 1 を返す。 */

int fall_all( void )
{
  int x,y,flag;

  flag = 0;
  for( y = 13 ; y > 1 ; y-- )
    for( x = 1 ; x < 7 ; x++ )
      if( Map_col[x][y] == NOTHING && Map_col[x][y-1] != NOTHING){
	Map_col[x][y] = Map_col[x][y-1];
	Map_col[x][y-1] = NOTHING;
	flag = 1;
      }
  if( flag )
    refresh();

  return flag;
}



/* ぷよ消去用サブルーチン */

static void chain_puyo( int x, int y )
{
  if( Map_col[x][y] != Color_target )
    return;

  Map_col[x][y] = KILLED;

  if( Killed < 3 ){
    Killed_x[Killed] = x;
    Killed_y[Killed] = y;
  }
  Killed++;

  chain_puyo( x+Dir_x[0],y+Dir_y[0] );
  chain_puyo( x+Dir_x[1],y+Dir_y[1] );
  chain_puyo( x+Dir_x[2],y+Dir_y[2] );
  chain_puyo( x+Dir_x[3],y+Dir_y[3] );
}



/* つながったぷよの消去および得点処理。一つでも消えたら 1 を返す。*/

int kill_puyo( void )
{
  int x,y,x2,y2,dir,kill_flag;

  start_calc();

  for( y = 1 ; y < 14 ; y++ )
    for( x = 1 ; x < 7 ; x++ ){
      Color_target = Map_col[x][y];
      if( Color_target >0 && Color_target < 7 ){
	Killed = 0;
	chain_puyo(x,y);
	if( Killed > 3 )
	  add_score( Killed );
	else
	  while( --Killed >= 0 )
	    Map_col[Killed_x[Killed]][Killed_y[Killed]] = Color_target;
      }
    }

  kill_flag = 0;

  for( y = 1 ; y < 14 ; y++ )
    for( x = 1 ; x < 7 ; x++ )
      if( Map_col[x][y] == KILLED ){
	Map_col[x][y] = NOTHING;
	kill_flag = 1;
	for( dir = 0 ; dir < 4 ; dir++ ){
	  x2 = x + Dir_x[dir];
	  y2 = y + Dir_y[dir];
	  if( Map_col[x2][y2] == WHITE_PUYO )
	    Map_col[x2][y2] = NOTHING;
	}
      }

  calc_score();

  return kill_flag;
}



/* 移動できるか？ */

int ismove(int x, int y)
{
  if( Map_col[x][y] == NOTHING )
    return 1;
  else
    return 0;
}



/* 仮想画面にぷよを置く */

void set_puyo(int x, int y, int col )
{
  Map_col[x][y] = col;
}



/* ゲームオーバー時のアニメーション (全ぷよが一段落ちる) */

void dead( void )
{
  int x,y;

  for( y = 14 ; y > 0 ; y-- )
    for( x = 1 ; x < 7 ; x++ )
      Map_col[x][y] = Map_col[x][y-1];

  refresh();
}
