/*******************************************************************/
/*******************************************************************/
/** BALLOON                                                       **/
/**   作成日：2001年1月30日                                       **/
/**   作成者：相田 翔(IDA SYO)                                    **/
/*******************************************************************/
/*******************************************************************/
/** 構成                                                          **/
/**   balloon.c:本体部                                            **/
/**   chara.h:キャラクタの設定・表示部                            **/
/**   menu.h:メニュー・アラーム処理部                             **/
/**   se.h:効果音の演奏部                                         **/
/*******************************************************************/
/*******************************************************************/

/*******************************************************************/
/* 本体部(balloon.c)                                               */
/* int watch(void):時計モードの処理                                */
/* void object_catch(int chr_pos, int *timer, rank *game_rank)     */
/*  :風船のキャッチの処理                                          */
/* int new_object_check(object_timer *obj_time, rank *game_rank)   */
/*  :風船の発生処理                                                */
/* int object_move                                                 */
/*  (int y_pos, int *timer, chr_fmt *character, rank *game_rank)   */
/*  :風船の移動処理                                                */
/* int miss_check                                                  */
/*  (int x_pos, int chr_pos, object_timer *time, rank *game_rank)  */
/*  :ミスのチェック処理                                            */
/* int gameover_menu(int score):ゲームオーバーの処理               */
/* int pause(int number):ポーズ処理                                */
/* int game(void):ゲームモードの処理                               */
/* void main(void):メイン処理                                      */
/*******************************************************************/

#include <sys/bios.h>
#include "chara.h"
#include "menu.h"
#include "se.h"

#ifndef ALL_KEY_PRESS
#define X_KEY (KEY_X1 | KEY_X2 | KEY_X3 | KEY_X4)
#define Y_KEY (KEY_Y1 | KEY_Y2 | KEY_Y3 | KEY_Y4)
#define OTHER_KEY (KEY_START | KEY_A | KEY_B)
#define ALL_KEY_PRESS (key_press_check() & (X_KEY | Y_KEY | OTHER_KEY))
#endif

/* モード */
#define WATCH_MODE 0
#define GAME_MODE 1
#define END_MODE 2

/* ゲーム速度の最大値と最小値（数字が大きいほど遅くなる） */
#define SPEED_MAX 80
#define SPEED_MIN 20

/* 風船の動くタイミング（風船が動くまでに行われる処理の回数） */
#define OBJ_TIMING 15

/* 風船の発生のタイミング（次の風船が発生するまでに行われる処理の回数） */
#define NEW_TIMING 10

/* 風船の１画面内の最大個数 */
#define OBJ_COUNT_MAX 8

/* 風船の最大個数の増加値 */
#define OBJ_COUNT_UP 5

/* 風船の移動・発生の有無の確認 */
#define OBJ_OFF 0
#define OBJ_ON 1

/* ミス時の戻り値 */
#define GAME_CONTINUE 0
#define GAME_OVER 1

/* ポーズ時のメニューからの戻り値 */
#define PAUSE_BACK MENU_BACK
#define EXIT MENU_EXIT


/* rank:ゲームデータ構造体 */
typedef struct {
	int game_speed; /* 速度のカウンタ */
	int speed_max; /* 速度のカウンタの最大値 */
	int obj_count; /* 風船の個数 */
	int count_max; /* 風船の個数の最大値 */
	int count_up; /* 風船の個数の最大値の増加分 */
	int score; /* スコア */
	int disp_score; /* 表示用スコア */
	int miss; /* ミス数 */
} rank;

/* object_timer:風船のカウントデータ構造体 */
typedef struct {
	int timer[(OBJ_COUNT + 1)];
} object_timer;


/************************************************/
/* 時計モードの処理を行う                       */
/* 戻り値:モード（GAME_MODE、END_MODEより指定） */
/************************************************/
int watch(void)
{
	int ply_pos = 0; /* プレイヤーの位置 */
	int ply_move = 1; /* プレイヤーの移動方向 */
	int ply_out = 0; /* プレイヤーアウト時の作業用カウンタ */
	int obj_pos[2] = {0, 0}; /* 風船の座標 */
	int obj_cnt = 0; /* 風船の個数 */
	int flip = WRITE; /* 表示・消去の指定用 */
	int timer = rtc_get_datetime(6); /* 秒のカウント用 */
	int i; /* ループカウンタ */

	/* 初期画面を表示する */
	screen_clear();
	time_write();
	chr_write(&player_dat[ply_pos], WRITE);

	while (ALL_KEY_PRESS);

	for (;;)
	{
		/* AまたはBボタンが押されたらゲームモードに移行する */
		if (key_press_check() & (KEY_A | KEY_B)) return GAME_MODE;

		/* スタートキーが押されたらメニューの処理を行う */
		if (key_press_check() & KEY_START)
			if (config_menu() == MENU_EXIT) return END_MODE;

		/* Y2またはY4ボタンが押されたら時間表示を切り替える */
		/* （Y2ボタン：12時間表示、Y4ボタン：24時間表示） */
		if (key_press_check() & KEY_Y2) hour_mode = hour_12;
		if (key_press_check() & KEY_Y4) hour_mode = hour_24;

		/* Y1またはY3ボタンが押されたらアラームの有効・無効を切り替える */
		/* （Y1ボタン：有効、Y3ボタン：無効） */
		if (key_press_check() & KEY_Y1) alarm_set.alarm_mode = ALARM_ON;
		if (key_press_check() & KEY_Y3) alarm_set.alarm_mode = ALARM_STOP;

		/* アラームチェックを行う */
		alarm_check();

		/* 前回の処理から１秒たっていなければ処理を行わない */
		if (timer == rtc_get_datetime(6)) continue;
		timer = rtc_get_datetime(6);

		/* 時刻を表示する */
		time_write();

		/* プレイヤーアウト時のエフェクトが終わったら通常状態に戻す */
		/* （エフェクトは８回で終了） */
		if (ply_out > 9)
		{
			for (i=0; i<OUT_COUNT; i++) chr_write(&ply_out_dat[i], DELETE);
			chr_write(&player_dat[(PLY_COUNT - 1)], DELETE);
			chr_write(&object_dat[obj_pos[0]][obj_pos[1]], DELETE);
			chr_write(&player_dat[ply_pos], WRITE);
			obj_pos[0] = 0;
			obj_pos[1] = 0;
			obj_cnt--;
			ply_out = 0;
			continue;
		}

		/* プレイヤーアウトならばエフェクトを開始する */
		if (ply_out > 0)
		{
			chr_write(&player_dat[ply_pos], DELETE);
			chr_write(&player_dat[(PLY_COUNT- 1)], WRITE);
			for (i=0; i<OUT_COUNT; i++)
				chr_write(&ply_out_dat[i], flip);
			flip ^= WRITE ^ DELETE;
			ply_out++;
			continue;
		}

		/* 風船をキャッチしたならば風船を消去して個数を減らす */
		if ((ply_pos == obj_pos[0]) && (obj_pos[1] == (OBJ_COUNT - 2)))
		{
			chr_write(&object_dat[obj_pos[0]][obj_pos[1]], DELETE);
			obj_cnt--;
		}

		/* 風船の移動・発生処理を行う（風船は画面上に１個まで） */
		if (obj_cnt == 0)
		{
			obj_pos[0] = (rand() % 4);
			obj_pos[1] = 0;
			chr_write(&object_dat[obj_pos[0]][obj_pos[1]], WRITE);
			obj_cnt++;
		}
		else
		{
			chr_write(&object_dat[obj_pos[0]][obj_pos[1]], DELETE);
			obj_pos[1]++;
			chr_write(&object_dat[obj_pos[0]][obj_pos[1]], WRITE);
		}

		/* 風船をキャッチし損なったならばプレイヤーアウトの状態に移行する */
		if ((obj_pos[1] == (OBJ_COUNT - 1)))
		{
			ply_out++;
			continue;
		}

		/* プレイヤーを移動させる */
		/* （左右に行ったりきたりする） */
		chr_write(&player_dat[ply_pos], DELETE);
		ply_pos += ply_move;
		chr_write(&player_dat[ply_pos], WRITE);
		if ((ply_pos == 0) || (ply_pos == (PLY_COUNT - 2))) ply_move *= -1;
	}
}


/********************************************/
/* 風船のキャッチの判定を行う               */
/* int chr_pos:プレイヤーの位置             */
/* int *timer:風船のタイマーへのポインタ    */
/* rank *game_rank:ゲームデータへのポインタ */
/********************************************/
void object_catch(int chr_pos, int *timer, rank *game_rank)
{
	int flip = WRITE; /* 表示・消去のしていよう（スコア点滅） */
	int i, j; /* ループカウンタ */

	/* 風船をキャッチしたならばキャッチの処理を行う */
	if (timer[(OBJ_COUNT - 2)] > 0)
	{
		/* アラーム中でなければキャッチ音を発生させる */
		if (alarm_set.alarm_mode != ALARM_START) sound_on(CATCH_SOUND);
		sys_wait(5);

		chr_write(&object_dat[chr_pos][(OBJ_COUNT - 2)], DELETE);
		timer[(OBJ_COUNT - 2)] = 0;
		game_rank->obj_count--;
		game_rank->score++;
		game_rank->disp_score++;

		/* スコアの調整を行い、表示する */
		/* （表示される点数は1000点で0点に戻り、データは9999点でストップ） */
		if (game_rank->disp_score > 999) game_rank->disp_score -= 1000;
		if (game_rank->score > 9999) game_rank->score = 9999;
		num_write(game_rank->disp_score, WRITE);

		/* 表示スコアが200点と500点になった時にミスをクリアする */
		if (((game_rank->disp_score == 200) || (game_rank->disp_score == 500))
		 && (game_rank->miss > 0))
		{
			for (i=0; i<8; i++)
			{
				chr_write(&miss_mes_dat, flip);
				for (j=0; j<game_rank->miss; j++)
					chr_write(&miss_mak_dat[j], flip);
				if (flip == WRITE) sound_on(CATCH_SOUND);
				sys_wait(20);
				sound_off();
				flip ^= (WRITE ^ DELETE);
				sys_wait(10);
			}
			chr_write(&miss_mes_dat, DELETE);
			for (j=0; j<game_rank->miss; j++)
				chr_write(&miss_mak_dat[j], DELETE);
			game_rank->miss = 0;
		}

		/* 風船の最大個数と速度を調整する */
		/*   最大個数：点数が規定値を越えるごとに増える */
		/*             規定値は(今までの規定値)+(増加値*2*(個数の最大値-1)) */
		if ((game_rank->score > game_rank->count_up) &&
		 (game_rank->count_max < OBJ_COUNT_MAX))
		{
			game_rank->count_max++;
			game_rank->count_up +=
			 (OBJ_COUNT_UP * 2 * (game_rank->count_max - 1));
		}

		/*   速度：10点ごとに、5ずつ速度カウンタを減少させる */
		/*         速度カウンタは次の移動を行うまで処理をループさせる回数 */
		if (((game_rank->score % 10) == 0) &&
		 (game_rank->speed_max > SPEED_MIN))
			game_rank->speed_max -= 5;

		/* 100点ごとに速度カウンタを30増やし、最大個数を2減らす */
		/* （最大個数の計算に使用する規定値も１つ前の状態に戻す） */
		if ((game_rank->score % 100) == 0)
		{
			game_rank->speed_max += 30;
			game_rank->count_max -= 2;
			game_rank->count_up -= (OBJ_COUNT_UP * 2 * (game_rank->count_max - 1));
		}

		/* アラーム中でなければキャッチ音を消去する */
		if (alarm_set.alarm_mode != ALARM_START) sound_off();
	}
}


/*******************************************************/
/* 風船の発生処理を行う                                */
/* 戻り値：風船の発生の有無（OBJ_ON、OBJ_OFFより指定） */
/* object_timer *obj_time:風船のタイマーへのポインタ   */
/* rank *game_rank:ゲームデータへのポインタ            */
/*******************************************************/
int new_object_check(object_timer *obj_time, rank *game_rank)
{
	static int timing = NEW_TIMING; /* 風船の発生間隔のタイマー */
	int rand_pos; /* 発生位置決定用の乱数 */
	int i, j; /* ループカウンタ */

	/* 風船の個数が最大値であるなら発生処理を行わない */
	if (game_rank->obj_count >= game_rank->count_max) return OBJ_OFF;

	/* 風船が重なる危険がある場合は発生処理を行わない */
	if (obj_time[(PLY_COUNT - 2)].timer[OBJ_COUNT] > 0) return OBJ_OFF;

	/* 発生間隔のタイマーを減少し0になるまでは処理を行わない */
	if (--timing > 0) return OBJ_OFF;

	/* 乱数で発生位置を決める */
	/* （隣の位置に風船があれば処理をやり直し */
	/*   10回の処理で決定できなければ処理を行わない） */
	for (i=0;;i++)
	{
		rand_pos = rand() % PLY_COUNT;
		if (rand_pos < (PLY_COUNT - 1))
		{
			for (j=0; j<2; j++)
				if (obj_time[rand_pos].timer[j] > 0) return OBJ_OFF;
			break;
		}
		if (rand_pos == (PLY_COUNT - 1))
		{
			for (j=0; j<(OBJ_COUNT - 1); j++)
				if (obj_time[(PLY_COUNT - 2)].timer[j] > 0) return OBJ_OFF;
			break;
		}
		if (i > 8) return OBJ_OFF;
	}

	/* アラーム無効であれば移動音を発生させる */
	if (alarm_set.alarm_mode != ALARM_START) sound_on(MOVE_SOUND);

	/* 風船を発生させる */
	if (rand_pos == (PLY_COUNT - 1))
	{
		chr_write(&object_dat[(PLY_COUNT - 2)][OBJ_COUNT], WRITE);
		obj_time[(PLY_COUNT - 2)].timer[OBJ_COUNT] = OBJ_TIMING;
	}
	else
	{
		chr_write(&object_dat[rand_pos][0], WRITE);
		obj_time[rand_pos].timer[0] = OBJ_TIMING;
	}

	/* 風船の個数、発生間隔のタイマーを変更する */
	game_rank->obj_count++;
	timing = NEW_TIMING * game_rank->obj_count;
	sys_wait(3);

	/* アラーム無効であれば発生した効果音を消去する */
	if (alarm_set.alarm_mode != ALARM_START) sound_off();

	return OBJ_ON;
}


/*******************************************************/
/* 風船を移動させる                                    */
/* 戻り値：風船の移動の有無（OBJ_ON、OBJ_OFFより指定） */
/* int y_pos:風船のY座標                               */
/* int *timer:対象列の風船のタイマーへのポインタ       */
/* chr_fmt *character:風船のパラメータへのポインタ     */
/* rank *game_rank:ゲームデータへのポインタ            */
/*******************************************************/
int object_move(int y_pos, int *timer, chr_fmt *character,rank *game_rank)
{
	/* 風船のタイマーを減少させる */
	if (timer[y_pos] > 0)
	{
		timer[y_pos]--;

		/* タイマーが0になってなければ何もしない */
		if (timer[y_pos] > 0) return OBJ_OFF;

		/* アラーム無効時のみ移動音を発生させる */
		if (alarm_set.alarm_mode != ALARM_START) sound_on(MOVE_SOUND);

		/* 風船を移動させる */
		chr_write(&character[y_pos], DELETE);
		chr_write
		 (&character[((y_pos == OBJ_COUNT) ? 3 : (y_pos + 1))], WRITE);

		/* 移動後のタイマー値をセット */
		/* 最上段のみ、タイマー値を少ない値にセットする */
		timer[((y_pos == OBJ_COUNT) ? 3 : (y_pos + 1))] =
		 (y_pos == (OBJ_COUNT - 3)) ? (OBJ_TIMING - 2) : OBJ_TIMING;
		sys_wait(3);

		/* アラーム無効時のみ移動音を消去する */
		if (alarm_set.alarm_mode != ALARM_START) sound_off();

		return OBJ_ON;
	}

	return OBJ_OFF;
}


/********************************************************************/
/* ミスのチェック、ミス時の処理を行う                               */
/* 戻り値：ゲームオーバーの判定（GAME_CONTINUE、GAME_OVERより指定） */
/* int x_pos:風船のX座標                                            */
/* int chr_pos:プレイヤーの座標                                     */
/* object_timer *time:風船のタイマーへのポインタ                    */
/* rank *game_rank:ゲームデータへのポインタ                         */
/********************************************************************/
int miss_check(int x_pos, int chr_pos, object_timer *time, rank *game_rank)
{
	int write_flag = WRITE; /* 表示・消去の指定用 */
	int i, j; /* ループカウンタ */

	/* ミスのチェックを行う */
	if (time[x_pos].timer[(OBJ_COUNT -1)] > 0)

	{
		/* ミス時の処理を行う */
		/*   風船の破裂したキャラクタを表示する */
		sound_on(MISS_SOUND);
		sys_wait(50);
		chr_write(&player_dat[chr_pos], DELETE);
		chr_write(&player_dat[(PLY_COUNT - 1)], WRITE);
		sound_off();
		sys_wait(50);

		/*   プレイヤーアウトのエフェクトを行う */
		for (i=0; i<8; i++)
		{
			sound_on(MISS_SOUND);
			for (j=0; j<OUT_COUNT; j++)
				chr_write(&ply_out_dat[j], write_flag);
			write_flag ^= (WRITE ^ DELETE);
			sys_wait(20);
			sound_off();
			sys_wait(10);
		}

		/*   ミスのカウントとミスマークの表示を行う */
		game_rank->miss++;
		if (game_rank->miss == 1) chr_write(&miss_mes_dat, WRITE);
		chr_write(&miss_mak_dat[(game_rank->miss - 1)], WRITE);

		/* ミスが３回になったらゲームオーバーへ移行する */
		if (game_rank->miss >= MAK_COUNT)
		{
			for (i=0; i<OUT_COUNT; i++)
				chr_write(&ply_out_dat[i], WRITE);
			return GAME_OVER;
		}

		sys_wait(50);

		/* プレイヤーを復帰させる */
		for (i=0; i<(OUT_COUNT - 1); i++)
			chr_write(&ply_out_dat[i], DELETE);
		chr_write(&player_dat[(PLY_COUNT - 1)], DELETE);

		/* 風船を全て消去する */
		for (i=0; i<(PLY_COUNT - 1); i++)
		{
			for (j=0; j<OBJ_COUNT; j++)
			{
				chr_write(&object_dat[i][j], DELETE);
				time[i].timer[j] = 0;
			}
		}
		chr_write(&player_dat[chr_pos], WRITE);
		game_rank->obj_count = 0;
	}

	/* ゲームを再開する */
	return GAME_CONTINUE;
}


/************************************************************/
/* ゲームオーバーの処理を行う                               */
/* 戻り値:モード（WATCH_MODE、GAME_MODE、END_MODEより指定） */
/* int score:スコア（表示用ではなく実際のスコア）           */
/************************************************************/
int gameover_menu(int score)
{
	static menu_body over_select; /* ゲームオーバー用のメニュー項目 */
	static menu_body exit_select; /* 終了確認用のメニュー項目 */
	static menu_body *pointer[3]; /* 各メニュー項目へのポインタ */

	/* ゲームオーバー用のメニュー項目の内容 */
	static char *over_index[MENU_ITEM_MAX] =
	 {"再スタート", "時計", "終了"}; /* 表示される項目 */
	static int over_child[MENU_ITEM_MAX] =
	 {MENU_NULL, MENU_NULL, 2}; /* 次の項目の場所 */
	static int over_action[MENU_ITEM_MAX] =
	 {ACTION_RESTART, ACTION_WATCH, NULL}; /* 選択時の動作 */

	/* 終了確認用のメニュー項目の内容 */
	static char *exit_index[MENU_ITEM_MAX] =
	 {"はい", "いいえ"}; /* 表示される項目 */
	static int exit_child[MENU_ITEM_MAX] =
	 {MENU_NULL, MENU_NULL}; /* 次の項目の場所 */
	static int exit_action[MENU_ITEM_MAX] =
	 {ACTION_EXIT, ACTION_CANCEL}; /* 選択時の動作 */

	static char work_buffer[11]; /* タイトル作成の作業用 */
	int i; /* ループカウンタ */

	/* メニュー項目へのポインタのセット */
	pointer[0] = NULL;
	pointer[1] = &over_select;
	pointer[2] = &exit_select;

	/* ゲームオーバー用のメニュー項目のセット */
	sprintf(work_buffer, "SCORE:%4d", score);
	over_select.title = work_buffer;
	over_select.parent = 1;
	over_select.item_max = 3;
	for (i=0; i<over_select.item_max; i++)
	{
		over_select.item[i].index = over_index[i];
		over_select.item[i].child = over_child[i];
		over_select.item[i].action = over_action[i];
	}

	/* 終了確認用のメニュー項目のセット */
	exit_select.title = "終了しますか？";
	exit_select.parent = 1;
	exit_select.item_max = EXIT_ITEM_MAX;
	for (i=0; i<exit_select.item_max; i++)
	{
		exit_select.item[i].index = exit_index[i];
		exit_select.item[i].child = exit_child[i];
		exit_select.item[i].action = exit_action[i];
	}

	/* メニューの表示 */
	menu_area_write(WRITE);
	menu_write(&over_select);

	/* メニュー選択の結果によってそれぞれのモードへ移行する */
	switch (menu_select(pointer, 1))
	{
	case ACTION_RESTART:
		return GAME_MODE;
	case ACTION_WATCH:
		return WATCH_MODE;
	case MENU_EXIT:
		return END_MODE;
	}
}


/***************************************************/
/* ポーズ時の処理を行う                            */
/* 戻り値:再開後の動作（PAUSE_BACK、EXITより指定） */
/* int score:表示用スコア                          */
/***************************************************/
int pause(int score)
{
	int timer = rtc_get_datetime(6); /* 秒のカウント用 */
	int flip = WRITE; /* 表示・消去の指定用 */

	while (ALL_KEY_PRESS);

	/* スタートキーでゲーム再開 */
	while (!(key_press_check() & KEY_START))
	{

		/* AまたはBボタンが押されたらメニュー処理を行う */
		if (key_press_check() & (KEY_A | KEY_B))
			if (config_menu() == MENU_EXIT) return EXIT;

		/* １秒おきにスコアを点滅させる */
		if (timer == rtc_get_datetime(6)) continue;
		flip ^= (WRITE ^ DELETE);
		if (flip == WRITE)
		{

			/* スコア表示の際に移動音を発生させる */
			sound_on(MOVE_SOUND);
			sys_wait(5);
			sound_off();

		}
		num_write(score, flip);
		timer = rtc_get_datetime(6);
	}

	while (ALL_KEY_PRESS);
	num_write(score, WRITE);
	return PAUSE_BACK;
}


/*************************************************************/
/* ゲームモードの処理を行う                                  */
/* 戻り値：モード（WATCH_MODE、GAME_MODE、END_MODEより指定） */
/*************************************************************/
int game(void)
{
	static object_timer obj_time[(PLY_COUNT - 1)]; /* 風船のタイマー */
	static rank game_rank; /* ゲームデータ */
	static int chr_pos = 0; /* プレイヤーの現在位置 */
	int obj_flag = OBJ_OFF; /* 風船の移動・発生の確認用 */
	int left_check = 0, right_check = 0; /* キーの押下状態確認用 */
	int i, j; /* ループカウンタ用 */


	/* ゲームデータを初期化する */
	game_rank.game_speed = SPEED_MAX;
	game_rank.speed_max = SPEED_MAX;
	game_rank.obj_count = 0;
	game_rank.count_max = 1;
	game_rank.count_up = OBJ_COUNT_UP;
	game_rank.score = 0;
	game_rank.disp_score = 0;
	game_rank.miss = 0;

	/* 風船のタイマーを初期化する */
	for (i=0; i<(PLY_COUNT - 1); i++)
	{
		for (j=0; j<(OBJ_COUNT + 1); j++) obj_time[i].timer[j] = 0;
	}

	/* 初期画面を表示する */
	screen_clear();
	chr_write(&player_dat[chr_pos], WRITE);
	num_write(game_rank.disp_score, WRITE);

	while (ALL_KEY_PRESS);

	for (;;)
	{
		/* スタートボタンが押されたらポーズ処理を行う */
		if (key_press_check() & KEY_START)
			if (pause(game_rank.score) == EXIT) return END_MODE;

		/* Y1またはY3ボタンが押されたらアラームの有効・無効を切り替える */
		/* （Y1ボタン：有効、Y3ボタン：無効） */
		if (key_press_check() & KEY_Y1) alarm_set.alarm_mode = ALARM_ON;
		if (key_press_check() & KEY_Y3) alarm_set.alarm_mode = ALARM_STOP;

		/* アラームチェックを行う */
		alarm_check();

		/* 左移動のボタンが押されたら移動の処理を行う */
		if (key_press_check() & left_key)
		{
			if ((left_check == 0) && (chr_pos > 0))
			{
				chr_write(&player_dat[chr_pos], DELETE);
				chr_pos--;
				chr_write(&player_dat[chr_pos], WRITE);
				object_catch(chr_pos, obj_time[chr_pos].timer, &game_rank);
			}
			left_check = 1;
		}
		else left_check = 0;

		/* 右移動のボタンが押されたら移動の処理を行う */
		if (key_press_check() & right_key)
		{
			if ((right_check == 0) && (chr_pos < (PLY_COUNT - 2)))
			{
				chr_write(&player_dat[chr_pos], DELETE);
				chr_pos++;
				chr_write(&player_dat[chr_pos], WRITE);
				object_catch(chr_pos, obj_time[chr_pos].timer, &game_rank);
			}
			right_check = 1;
		}
		else right_check = 0;

		/* 風船の速度カウンタを減少させ、0になったならば移動・発生処理を行う */
		game_rank.game_speed--;
		if (game_rank.game_speed > 0) continue;
		game_rank.game_speed = game_rank.speed_max;

		obj_flag = OBJ_OFF;

		/* 風船の発生処理を行う */
		if (new_object_check(obj_time, &game_rank) == OBJ_ON) continue;

		/* 風船の移動処理を行う */
		for (i=0; ((i<(PLY_COUNT - 1)) && (obj_flag == OBJ_OFF)); i++)
		{
			for (j=0; ((j<(OBJ_COUNT - 1)) && (obj_flag == OBJ_OFF)); j++)
			{
				obj_flag =
				 object_move(j, obj_time[i].timer, object_dat[i], &game_rank);
				if (miss_check(i, chr_pos, obj_time, &game_rank) == GAME_OVER)
					return gameover_menu(game_rank.score);
				object_catch(chr_pos, obj_time[chr_pos].timer, &game_rank);
			}
		}

		if (obj_flag == OBJ_ON) continue;

		obj_flag = object_move(OBJ_COUNT, obj_time[(PLY_COUNT - 2)].timer,
		 object_dat[(PLY_COUNT - 2)], &game_rank);
		if (miss_check((PLY_COUNT - 2), chr_pos, obj_time, &game_rank)
		 == GAME_OVER)
			return gameover_menu(game_rank.score);
		object_catch(chr_pos, obj_time[chr_pos].timer, &game_rank);
	}
}


/********************/
/* メイン処理を行う */
/********************/
void main(void)
{
	int now_mode = WATCH_MODE; /* 現在のモード */

	/* それぞれの初期化処理を行う */
	srand(sys_get_tick_count()); /* 乱数発生の準備 */
	display_init(); /* 画面・キャラクタの初期化 */
	screen_clear(); /* 画面の全消去 */
	init_sound(); /* 効果音の初期化 */

	/* アラームのパラメータの初期化を行う */
	alarm_set.alarm_time[0] = 0;
	alarm_set.alarm_time[1] = 0;
	alarm_set.alarm_mode = ALARM_OFF;
	alarm_set.char_mode = ALM_A;
	alarm_set.second_check = 60;
	hour_mode = hour_12;

	/* 各モードへ移行する */
	do {
		switch (now_mode)
		{
		/* 時計モードへ */
		case WATCH_MODE:
			now_mode = watch();
			break;
		/* ゲームモードへ */
		case GAME_MODE:
			now_mode = game();
			break;
		/* 終了 */
		case END_MODE:
			break;
		}
	} while (now_mode != END_MODE);
}
