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

		パズル「かさねがさね」

						メイン

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

#include	"common.h"
#include	"kasane.h"
#include	"screen.h"
#include	"pad.h"
#include	"sound.h"


CHIP	x_chip[LEN], y_chip[LEN];			/* チップ */
int		cursor_x, cursor_y;					/* カーソル */
int		cursor_flag;						/* カーソルの状態 */

static int	x_answer[LEN], y_answer[LEN];	/* 解答 */


/************************
    チップデータ初期化
 ************************/
static
void	set_chip(void)
{
#define		check_edge(c, n)	((((n) == (c).min/2) \
										|| ((n) == (c).max/2 - 1)) \
													&& ((c).min < (c).max - 2))
												/* 端チェック */
	int		x, y, cnt;

	for (cnt = 0; cnt < LEN; cnt++) {			/* 盤をチップで埋める */
		x_chip[cnt].min = 0;
		x_chip[cnt].max = LEN*2;
		y_chip[cnt].min = 0;
		y_chip[cnt].max = LEN*2;
	}

	cnt = LEN*LEN*(128 + rnd(40))/256;
	while ( cnt > 0 ) {
		x = rnd(LEN);
		y = rnd(LEN);
		if ( check_edge(x_chip[y], x) && check_edge(y_chip[x], y) ) {
			if ( x == x_chip[y].min/2 ) {		/* 左端 */
				x_chip[y].min += 2;
			}
			else {								/* 右端 */
				x_chip[y].max -= 2;
			}
			if ( y == y_chip[x].min/2 ) {		/* 上端 */
				y_chip[x].min += 2;
			}
			else {								/* 下端 */
				y_chip[x].max -= 2;
			}
			cnt--;
		}
	}

	for (cnt = 0; cnt < LEN; cnt++) {
		x_answer[cnt] = x_chip[cnt].min;				/* 解答保存 */
		y_answer[cnt] = y_chip[cnt].min;

		x_chip[cnt].max -= x_chip[cnt].min;				/* 左揃え */
		x_chip[cnt].min = 0;
		y_chip[cnt].min += LEN*2 - y_chip[cnt].max;		/* 下揃え */
		y_chip[cnt].max = LEN*2;
	}
}

/******************************
    クリアチェック
		戻り値	クリアしたか
 ******************************/
static
Bool	check_clear(void)
{
	int		x, y;

	for (y = 0; y < LEN; y++) {
		for (x = x_chip[y].min/2; x < x_chip[y].max/2; x++) {
			if ( (y < y_chip[x].min/2) || (y >= y_chip[x].max/2) ) {
				return	FALSE;
			}
		}
	}
	return	TRUE;
}

/******************************
    チップ横移動
		引数	y = 行
				d = 移動方向
 ******************************/
static
void	move_x(int y, int d)
{
	int		i;

	for (i = 0; i < 2; i++) {
		x_chip[y].min += d;				/* 移動 */
		x_chip[y].max += d;
		set_x_chip(y);					/* ＢＧ設定 */
		draw_screen();					/* 描画 */
		draw_screen();
	}
}

/******************************
    チップ縦移動
		引数	x = 列
				d = 移動方向
 ******************************/
static
void	move_y(int x, int d)
{
	int		i;

	for (i = 0; i < 2; i++) {
		y_chip[x].min += d;				/* 移動 */
		y_chip[x].max += d;
		set_y_chip(x);					/* ＢＧ設定 */
		draw_screen();					/* 描画 */
		draw_screen();
	}
}

/****************
    解答を表示
 ****************/
static
void	show_answer(void)
{
	int		i;

	for (i = 0; i < LEN; i++) {
		while ( x_chip[i].min < x_answer[i] ) {
			move_x(i, 1);
		}
		while ( x_chip[i].min > x_answer[i] ) {
			move_x(i, -1);
		}
		while ( y_chip[i].min < y_answer[i] ) {
			move_y(i, 1);
		}
		while ( y_chip[i].min > y_answer[i] ) {
			move_y(i, -1);
		}
	}
}

/************************************
    ゲームメイン
		戻り値	 TRUE : ゲーム続行
				FALSE : 終了
 ************************************/
static
Bool	game_main(void)
{
	static int	back = 0;
	PAD		pad;
	int		i;

	set_chip();								/* チップ初期化 */
	for (i = 0; i < LEN; i++) {				/* チップ描画用バッファ設定 */
		set_x_chip(i);
		set_y_chip(i);
	}
	cursor_x = LEN/2;
	cursor_y = LEN/2;
	cursor_flag = 1;

	draw_back(back);						/* 背景描画 */
	back ^= 0x01;
	draw_screen();							/* 画面描画 */
	fade_in();								/* フェードイン */
	play_music(BGM_MAIN, PLAY_LOOP);		/* BGM再生開始 */
	while ( !(get_pad() & KEY_START) ) {
		draw_screen();						/* 画面描画 */
		if ( check_clear() ) {				/* クリア */
			play_music(BGM_CLEAR, PLAY_SINGLE);
			cursor_flag = -1;
			return	wait_clear();
		}

		pad = get_rept();
		if ( get_pad() & (KEY_A | KEY_B) ) {		/* チップ移動 */
			cursor_flag = 0;
			if ( (pad & KEY_RIGHT1) && (x_chip[cursor_y].max < LEN*2) ) {
				move_x(cursor_y, 1);
			}
			else if ( (pad & KEY_LEFT1) && (x_chip[cursor_y].min > 0) ) {
				move_x(cursor_y, -1);
			}
			if ( (pad & KEY_DOWN1) && (y_chip[cursor_x].max < LEN*2) ) {
				move_y(cursor_x, 1);
			}
			else if ( (pad & KEY_UP1) && (y_chip[cursor_x].min > 0) ) {
				move_y(cursor_x, -1);
			}
		}
		else {										/* カーソル移動 */
			cursor_flag = 1;
			if ( (pad & KEY_RIGHT1) && (cursor_x < LEN-1) ) {
				cursor_x++;
			}
			else if ( (pad & KEY_LEFT1) && (cursor_x > 0) ) {
				cursor_x--;
			}
			if ( (pad & KEY_DOWN1) && (cursor_y < LEN-1) ) {
				cursor_y++;
			}
			else if ( (pad & KEY_UP1) && (cursor_y > 0) ) {
				cursor_y--;
			}
		}

		if ( pad & KEY_Y1 ) {
			show_answer();					/* 解答表示 */
		}
	}
	fade_out();								/* フェードアウト */
	fadeout_music();						/* ＢＧＭフェードアウト */
	for (i = 0; i < FADE_COUNT; i++) {
		draw_screen();
	}
	return	FALSE;
}

/************
    メイン
 ************/
int		main(int argc, char* argv[])
{
	res_t far*	res;

	res = init_screen(_pc->_resource);				/* 画面初期化 */
	res = init_sound(res);							/* サウンド初期化 */

	srand((u_int)(sys_get_tick_count() & 0x7fff));	/* 乱数初期化 */
	while ( game_main() );							/* ゲームメイン */
	end_sound();									/* サウンド終了 */

	return	0;
}

/**************** End of File **********************************************/