/*****************************************
  xjump version 3

  floor.c

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

#include<stdio.h>
#include<X11/Xlib.h>

#include"xjump.h"


/* 変数 */

static floor_t Floor[HEIGHT];
static int Map_index;
static int Floor_top;

static int Floor_current;

static int Level;
static int Level_add;

 
/* 床を描画 */

void FLOOR_draw( floor_t *fp )
{
  int len;


  len = fp->right - fp->left + 1;
  if( len > 0 )
    XCopyArea(Disp,Floor_p[fp->graphic],Scr_d,Gc_nomask,
  		fp->phase,0,len,16,fp->left,fp->y);
  if( fp->erase_width )
    XClearArea(Disp,Scr_d,fp->erase_x,fp->erase_y,fp->erase_width,16,False);

}


/* 床を更新 */

void FLOOR_refresh( void )
{
  int y;
  floor_t *fp;

  for( y = 0, fp = Floor ; y < HEIGHT ; y++, fp++ )
    FLOOR_draw(fp);
}


/* 床を設定 */

void FLOOR_create( int y )
{
  int f,x1,x2,l,fvec;
  floor_t *fp;
  int prob;
  int level;
  static int fpos = WIDTH/2;

  f = Floor_top - y;
  fp = Floor + (y + Map_index) % HEIGHT;
  fp->y = y*16;
  fp->phase = 0;	


  if( f % 250 == 0 ){

    fp->floor = Floor_current++;

    fp->left_src = fp->left = 16;
    fp->right_src = fp->right = WIDTH*16-17;
    fp->mu = 1;
    fp->move_vector = 0;
    fp->blink_interval = 0;
    fp->force_vector = 0;
    fp->blink_count = 0;
    fp->graphic = FLOOR_NORMAL;
    return;
  }

  if( f % FLOOR_HEIGHT == 0 ){

    fp->floor = Floor_current;
    level = Level / 60 + Floor_current + Level_add;
    Floor_current++;

    prob = 100 - 10000 / (level+100);

    fvec = (rnd(2)*2-1) * ( rnd( (WIDTH-11)/4 ) + (WIDTH-11)/4 );
    fpos = ( fpos + fvec +WIDTH-11 ) % (WIDTH-11);
    
    x1 = ( fpos+5 - rnd( 3 ) - 2)*16;
    x2 = ( fpos+5 + rnd( 3 ) + 2)*16+15;

    fp->left_src = fp->left = x1;
    fp->right_src = fp->right = x2;

    if( rnd(120)+20 > prob ){
      fp->graphic = FLOOR_NORMAL;
      fp->mu = 1;
      fp->force_vector = 0;
    }else if( rnd(100) > 50 ){
      fp->graphic = FLOOR_ICE;
      fp->mu = 0;
      fp->force_vector = 0;
    }else{
      fp->graphic = FLOOR_FORCE;
      fp->force_vector = (rnd(2)*3-1)*(rnd(4)+1);
      fp->mu = 1;
    }

    fp->graphic_base = fp->graphic;

    if( rnd(100)+50 < prob ){
      fp->blink_interval = rnd(76)+25;
      fp->blink_count = rnd(fp->blink_interval);
      if( rnd(100) > 50 )
        fp->graphic = FLOOR_CLEAR;
    }else{
      fp->blink_interval = 0;
      fp->blink_count = 0;
    }

    if( rnd(100) + 10 < prob )
      fp->move_vector = rnd(9)-4;
    else
      fp->move_vector = 0;

    return;
  }

  fp->left = WIDTH*16;
  fp->right = 0;
  fp->blink_interval = 0;
  fp->blink_count = 0;
}


/* 床の処理 */

void FLOOR_move( floor_t *fp, int scroll )
{
  int left,right,left2,right2,tmp;

  fp->erase_y = fp->y;
  fp->erase_width = 0;

  if( fp->left > fp->right )
    return;

  left2 = left = fp->left;
  right2 = right = fp->right;

  if( fp->move_vector ){
    left += fp->move_vector;
    right += fp->move_vector;
    if( left < 16 || right >= (WIDTH-1)*16 ){
      left = left2;
      right = right2;
      fp->move_vector = -fp->move_vector;
    }else{
      if( fp->move_vector > 0 ){
        fp->erase_x = left2;
        fp->erase_width = fp->move_vector;
      }else{
        fp->erase_x = right2 + fp->move_vector + 1;
        fp->erase_width = -fp->move_vector;
      }
    }
  }

  if( scroll ){
    fp->y += 16;
    fp->erase_x = left2;
    fp->erase_width = right2 - left2 + 1;
  }

  if( fp->blink_interval ){
    fp->blink_count--;
    if( fp->blink_count <= 0 ){
      fp->blink_count = fp->blink_interval;
      if( fp->graphic == fp->graphic_base ){
        fp->graphic = FLOOR_CLEAR;
      }else{
        fp->graphic = fp->graphic_base;
        fp->phase = 0;
      }
    }
  }

  fp->left = left;
  fp->right = right;
  if( fp->graphic == FLOOR_CLEAR )
    fp->phase = left & 31;
  else
    fp->phase = (fp->phase - fp->force_vector + 32) & 31;
}


void FLOOR_move_all( int scroll )
{
  int y;
  floor_t *fp;

  Level++;

  for( y = 0, fp = Floor ; y < HEIGHT ; y++, fp++ )
    FLOOR_move(fp,scroll);

  if( scroll ){
    Floor_top++;
    if( --Map_index < 0 )
      Map_index = HEIGHT - 1;
    FLOOR_create( 0 );
  }
}


/* 床を調べる */

floor_t *FLOOR_check(int hx, int hy)
{
  int y;
  floor_t *fp;

  y = ( (hy + 64) / 16 );
  if( y < 0 || y >= HEIGHT )
    return NULL;

  fp = Floor + (y + Map_index) % HEIGHT;

  if( fp->left < hx+28 && hx+4 < fp->right )
    return fp;
  else
    return NULL;
}


/* 初期化 */

void FLOOR_init( int level )
{
  int x,y;

  Floor_top = HEIGHT - 4;
  Floor_current = 1;
  Map_index = 0;
  Level = 0;
  Level_add = level;

  XClearWindow(Disp,Scr_d);

  for ( y = 0 ; y < HEIGHT ; y++ )
    Floor[y].erase_width = 0;

  for ( y = HEIGHT-1 ; y >= 0 ; y-- )
    FLOOR_create(y);

  for ( y = 0 ; y < HEIGHT ; y++ )
    FLOOR_draw(Floor+y);
}
