/******************************************************************/
/*	ＣＲＡＺＹ ＢＡＬＬＯＯＮ ＰＲＯ６８Ｋ
		Ｉ／Ｏ合本 ＭＺ−８０活用研究よりの移植
      Ａｒｒａｎｅｄ　１９９２,９４  ｂｙ  ＡＩＧ−ＳＯＦＴ       */
/******************************************************************/

#include <stdio.h>
#include <string.h>
#include <music.h>
#include <process.h>
#include <doslib.h>
#include <iocslib.h>
#include "defines.h"
#include "aigtext.h"
#include "menu.h"
#include "menus.h"
#include "skey.h"
#include "aenv.h"
#include "amacro.h"

char prog[]="@@> CB.C : 1997/11/09 SUN : GAME : CRAZY_BALLOON";

/* '92/04/12 : 初期バージョン */
/* '92/04/13 : 面データ変更可能 */
/* '92/04/16 : PANIC期間内時間経過防止 */
/* '92/04/19 : ADPCMデータ最初に読み込み */
/* '92/07/26 : JOYSTICKバグ修正 */
/* '94/08/16 : skey.h対応 */
// '97/10/04 : 新vwait対応
// '97/11/09 : 画面モード強制変更(ファイラーからの直接起動対応)
/******************************************************************/
/* 定数定義 */

/* 画面幅 */
#define DX	96		/* 実画面幅 */
#define WX	(DX/2)		/* 仮想画面Ｘ幅 */
#define WY	31		/* 仮想画面Ｙ幅（実画面Ｙ幅と一致）*/

/* 仮想画面内ゲームフィールド座標 */
#define HX	4		/* ホーム座標 */
#define HY	5
#define FWX	40		/* フィールドＸ幅 */
#define FWY	25		/* フィールドＹ幅 */
#define EX	(HX+FWX-1)	/* エンド座標 */
#define EY	(HY+FWY-1)

/* リターン値定数 */
#define	READY		0	/* そのまま */
#define	MENCLEAR	1	/* 面クリア */
#define GAMEOVER	2	/* ゲームオーバー */
#define EXITOVER	3	/* 強制中断 */
#define ERROR		4	/* 面データエラー */

#define EXITCUT		'!'	/* 強制中断キー */

/* 壁 */
#define KABE1	'/'	/* ☆	8199 */
#define KABE2	'='	/* ★	819a */
#define KABE3	'.'	/* ○	819b */
#define KABE4	','	/* ●	819c */
#define KABE5	'@'	/* ◎	819d */
#define KABE6	'|'	/* ◇	819e */
#define KABE7	':'	/* ◆	819f */
#define KABE8	'%'	/* □	81a0 */
#define KABE9	'$'	/* ■	81a1 */
#define KABE10	'<'	/* △	81a2 */
#define KABE11	'>'	/* ▲	81a3 */
#define KABE12	'['	/* ▽	81a4 */
#define KABE13	']'	/* ▼	81a5 */
#define KABE14	'*'	/* ＊	8196 */
#define WAKU	'+'	/* 外枠 */

#define START	'`'	/* SHIFT+@ */
#define GOAL	'\\'
#define BALN	'\?' 	/* 残り表示の風船 */

/* 風船構成部品 */
#define BBALNS	11	/* 風船構成部品数 */
#define BALN0	'('
#define BALN1	'~'
#define BALN2	')'
#define BALN3	'{'
#define BALN4	'}'
#define BALN5	BALN2
#define BALN6	'_'
#define BALN7	BALN0
#define BALN8	'&'
#define BALN9	BALN8
#define BALN10	'#'
/* 破裂した時の部品 */
#define BALN11	'^'
#define BALN12	'!'
#define BALN13	'-'

/* その他定数 */
#define BALNS	4		/* 初期風船数 */
#define GMAX	(40*2+(25-2)*2)	/* ゴール領域数 */

/******************************************************************/
/* グローバル変数 */

int bx,by;			/* 風船座標 */
int bsx,bsy;			/* 風船スタート座標 */
int bax[BBALNS],bay[BBALNS];	/* 風船構成部品座標 */
int bac[BBALNS];		/* 風船構成部品表 */
int balns;			/* 風船残り数 */
int m=1,d=1;			/* 風船揺れフラグ */

int gl;				/* ゴール領域数 */
int gx[GMAX],gy[GMAX];		/* ゴール領域座標 */

int tm;				/* スタート時間 */
int stime,htime;		/* 時間 */
int ptime;			/* パニックタイム */

int fdemo;			/* オープニングデモ中かどうかのフラグ */

unchar *pon,*bang;		/* ADPCMバッファー */
int pon_len,bang_len;		/* バッファーサイズ */

unchar *exec;			/* PANIC 起動プログラム */

/******************************************************************/
/* フォント設定 */

struct FNTBUF
f_ec56 = {16,16 /* 風船構成部品３ */
	,{
	0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,
	0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,
	0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,
	0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}
},
f_ec57 = {16,16 /* 風船構成部品４ */
	,{
	0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
	0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
	0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
	0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01}
},
f_ebea = {16,16 /* 風船構成部品８,９ */
	,{
	0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x08,
	0x08,0x10,0x04,0x20,0x02,0x40,0x01,0x80,
	0x01,0x80,0x02,0x40,0x04,0x20,0x08,0x10,
	0x10,0x08,0x20,0x04,0x40,0x02,0x80,0x01}
},
f_ebf6 = {16,16 /* 外枠 */
	,{
	0xcc,0xcc,0xcc,0xcc,0x33,0x33,0x33,0x33,
	0xcc,0xcc,0xcc,0xcc,0x33,0x33,0x33,0x33,
	0xcc,0xcc,0xcc,0xcc,0x33,0x33,0x33,0x33,
	0xcc,0xcc,0xcc,0xcc,0x33,0x33,0x33,0x33}
},
f_ebf2 = {16,16 /* 風船構成部品１０ */
	,{
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}
};

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

void main(int argc,unchar *argv[])
{
int ret;
FILE *fp;
unchar menfile[MAXPATH],rechigh[MAXPATH];

	/* 初期化 */
	CRTMOD(16); // cwidth(96);
	help_set(argv[0],0);
	init();
	/* 面ファイル名 */
	fn_ext((argc>1? argv[1]:"CB.MEN"),menfile,"MEN"); /* 拡張子補足 */
	
	/* ハイスコア設定 */
	htime=0; /* ハイスコアクリア */
	{ /* ハイスコアファイル名は面データごとに変える */
	unchar drv[MAXDRIVE],dir[MAXDIR],fname[MAXFNAME],ext[MAXEXT];
		strsfn2(menfile,drv,dir,fname,ext);
		strmfn(rechigh,drv,dir,fname,"HSC");
	}
	fp=fopen(rechigh,"rb");
	if (fp!=NULL) { /* 最高速時間 read */
		fread(&htime,sizeof(htime),1,fp);
		fclose(fp);
	}
	
	do {
		curoff(); /* cursor off */
		
		init_balloon(); /* 風船部品初期化 */
		if (start()) {
			ret=EXITOVER;
			curon();
			break;
		}
		fdemo=0;
		
		play_music("|:20C32G32:|");
		vwait(19);
		
		balns=BALNS;	/* 風船残り数 */
		stime=0;	/* 経過時間＝０ */
		ptime=0;	/* パニックタイム＝０ */
		/* 画面初期化 */
		if (init_screen(menfile)) {
			ret=ERROR;
			curon();
			break;
		}
		bx=bsx; by=bsy;	/* スタート地点へ */
		bax[0]=-1;	/* 最初の印 */
		m=1; d=1;	/* 風船揺れフラグセット */
		
		do { /* メインループ */
			/* 時間表示 */
			ch_time();
			vwait(3);
			/* 風船表示＆当たり判定 */
			if (print_balloon()) {
				vwait(2);
				break_balloon();
				balns--;
				balns_left();
				if (balns==0) {
					ret=GAMEOVER;
					break;
				}
				bx=bsx;
				by=bsy;	/* スタートからやり直し */
				init_balloon(); /* 風船部品初期化 */
				vwait(26);
				continue;
			}
			vwait(3);
			/* 風船移動 */
			ret=balloon_move();
			if (ret!=READY) break;
			
			/* ゴールイン判定 */
			ret=goalin();
			vwait(3);
		} while (ret==READY);
		if (ret==EXITOVER) { /* 強制中断 */
			curon();
			break;
		}
		vwait(26);
		
		/* ゲーム終了 */
		if (ret==GAMEOVER) message("☆☆ ＧＡＭＥ　ＯＶＥＲ ☆☆",4);
		else {
			message("★☆★ ゴールイン！！ ★☆★",4);
			if (htime==0 || stime<htime) {
				message("＊＊　新記録！！　＊＊",4);
				htime=stime;
				hi_time();
				beep();
			}
		}
		center("もう一度しますか？",17);
		curon();
		do {
			ret=toupper(KFLUSHGC());
		} while (ret!='Y' && ret!='N' && ret!=ESC);
		ret=(ret=='Y');
	} while (ret);
	/* 正常終了ならret=0 : exit code */
	crlf();
	m_stop('NASI','NASI','NASI','NASI','NASI','NASI','NASI','NASI');
	
	/* ハイスコア記録 */
	fp=fopen(rechigh,"wb");
	if (fp!=NULL) { /* 最高速時間 write */
		fwrite(&htime,sizeof(htime),1,fp);
		fclose(fp);
	}
	
	/* ADPCMバッファー開放 */
	if (pon!=NULL) free(pon);
	if (bang!=NULL) free(bang);
	exit(ret);
}

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

int goalin()
/* ゴールイン判定 */
{
int i,j;
	for (i=0;i<gl;i++) {
		for (j=0;j<BBALNS;j++) {
			if (bay[j]==gy[i] && bax[j]==gx[i]) {
				if (play_music("G4R32G8R32G8R32G2.R8G+4G4G+4R32G4R32G8R32G8R32G2.R8G4A4B4<C1>")==-1) {
					bell(3);
				}
				return(MENCLEAR);
			}
		}
	}
	return(READY);
}

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

init()
/* 初期化 */
{
	/* 乱数初期化 */
	srand2();
	
	/* PANIC起動プログラム名 */
	exec=getenv2("PANIC","COMMAND.X");
	
	/* 音楽初期化 */
	m_init();
	play_music("V12@13");
	
	/* ADPCM読み込み */
	/* 破裂音はＳＸ−ＣＯＬＵＭＳより拝借 */
	pon_len=fmalloc(&pon,"PON.PCM",0,0);
	bang_len=fmalloc(&bang,"BANG.PCM",0,0);
}

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

int init_screen(unchar *menfile)
/* 画面初期化 */
{
	init_tvram();	/* 仮想テキストＶＲＡＭクリア */
	cls();		/* 実テキスト画面クリア */
	title();	/* タイトル表示 */
	balns_left();	/* 残り風船数表示 */
	
	/* ゲーム画面ロード＆作成 */
	return(make_men(menfile));
}

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

title()
/* タイトル表示 */
{
	center("＊＊　ＣＲＡＺＹ ＢＡＬＬＯＯＮ − ＰＲＯ６８Ｋ　＊＊",0);
	sc_time();
	hi_time();
}

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

balns_left()
/* 残り風船表示 */
{
int i,x,y;
	B_LOCATE(47,3);
	i=B_PRINT("残り風船:");
	x=(i>>16)/2;
	y=i&0xffff;
	/* printxy()による表示はＸ＝偶数座標からなので注意 */
	for (i=0;i<balns;i++) printxy(x+i,y,BALN);
	printxy(x+i,y,SPC);
}

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

ch_time()
/* 時間経過チェック */
{
int tim;
	time(&tim);
	if (tim-ptime-tm!=stime) {
		stime++;
		sc_time();
	}
}

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

sc_time()
/* 経過時刻表示 */
{
	B_LOCATE(26,2);
	B_PRINT("経過時間:");
	print_time(stime);
}

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

hi_time()
/* 最高速時間表示 */
{
	B_LOCATE(47,2);
	B_PRINT("最高速時間:");
	print_time(htime);
}

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

print_time(int tim)
/* 時刻表示サブルーチン */
{
	print_decII(tim/60,'0',2); /* 分 */
	B_PUTC(':');
	print_decII(tim%60,'0',2); /* 秒 */
}

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

int start()
/* 説明＆オープニングデモ */
{
int h,c;
int tim;
	fdemo=1; /* デモ中！１ */
	while (1) {
		cls();
		init_tvram();
		title();
		bax[0]=-1; /* 最初の印 */
		by=1;
		for (h=11;h<=29;h+=2) {
			bx=h+1;
			for (m=1;m<=5;m++) {
				c=getky();
				if (c==SPC) goto ST;
				if (c==EXITCUT) return(EXITOVER);
				print_balloon();
				vwait(6);
			}
			for (m=5;m>=1;m--) {
				c=getky();
				if (c==SPC) goto ST;
				if (c==EXITCUT) return(EXITOVER);
				print_balloon();
				vwait(6);
			}
			switch (h) {
				case 13:printxy2(h-1,6,'B');
					printxy2(h-2,2,'C');
					beep();
					break;
				case 15:printxy2(h-1,6,'A');
					printxy2(h-2,2,'R');
					beep();
					break;
				case 17:printxy2(h-1,6,'L');
					printxy2(h-2,2,'A');
					beep();
					break;
				case 19:printxy2(h-1,6,'L');
					printxy2(h-4,4,KABE5);
					beep();
					break;
				case 21:printxy2(h-1,6,'O');
					printxy2(h-4,2,'Z');
					beep();
					break;
				case 23:printxy2(h-1,6,'O');
					printxy2(h-4,2,'Y');
					beep();
					break;
				case 25:printxy2(h-1,6,'N');
					beep();
					break;
			}
			vwait(9);
		}
		kbox(9,0,26,8,KABE5);
		
		fdemo=2; /* デモ中！２ */
		setumei(); /* 説明表示 */
		play_music("|:20A32<C32>:|");
		
		bx=30;
		time(&tm);
		do {
			for (m=2;m<=5;m++) {
				c=getky();
				if (c==SPC) goto ST;
				if (c==EXITCUT) return(EXITOVER);
				print_balloon();
				vwait(7);
			}
			for (m=5;m>=1;m--) {
				c=getky();
				if (c==SPC) goto ST;
				if (c==EXITCUT) return(EXITOVER);
				print_balloon();
				vwait(7);
			}
			time(&tim);
		} while (tim-tm<10); /* 10sec */
	}
    ST:
	time(&tm); /* スタート時間記録 */
	return(READY);
}

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

setumei()
/* 説明表示 */
{
	B_LOCATE(HX+12*2,HY+10); B_PRINT("風船をうまくゴールに入れて下さい。");
	B_LOCATE(HX+12*2,HY+11); B_PRINT("風船は４個あります。");
	B_LOCATE(HX+18*2,HY+13);     B_PRINT("８");
	B_LOCATE(HX+18*2,HY+14);     B_PRINT("↑");
	B_LOCATE(HX+16*2,HY+15); B_PRINT("４←♀→６");
	B_LOCATE(HX+18*2,HY+16);     B_PRINT("↓");
	B_LOCATE(HX+18*2,HY+17);     B_PRINT("２");
	B_LOCATE(HX+10*2,HY+20); B_PRINT("ＰＵＳＨ ［ＳＰＡＣＥ］ ＫＥＹ");
}

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

init_balloon()
/* 風船部品初期化 */
{
	/* 風船構成部品定義 */
	bac[0]=BALN0;
	bac[1]=BALN1;
	bac[2]=BALN2;
	bac[3]=BALN3;
	bac[4]=BALN4;
	bac[5]=BALN5;
	bac[6]=BALN6;
	bac[7]=BALN7;
	bac[8]=BALN8;
	bac[9]=BALN9;
	bac[10]=BALN10;
}

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

int print_balloon()
/* 風船表示 */
/* return : 0=ok , 1=break */
{
int x,i;
	/* 今表示している風船を消す（表示していない時＝最初は消さない）*/
	if (bax[0]!=-1) for (i=0;i<BBALNS;i++) printxy2(bax[i],bay[i],SPC);
	
	x=bx-(3-m);
	bax[0]=x;    bay[0]=by;
	bax[1]=x+1;  bay[1]=by;
	bax[2]=x+2;  bay[2]=by;
	
	bax[3]=x;    bay[3]=by+1;
	bax[4]=x+2;  bay[4]=by+1;
	
	bax[5]=x;    bay[5]=by+2;
	bax[6]=x+1;  bay[6]=by+2;
	bax[7]=x+2;  bay[7]=by+2;
	
	bax[8]=x+1;  bay[8]=by+3;
	
	bay[9]=by+4;
	if (m>3 ) bax[9]=x;
	if (m==3) bax[9]=x+1;
	if (m<3 ) bax[9]=x+2;
	
	bax[10]=x+4-m; bay[10]=by+5;
	
	for (i=0;i<BBALNS;i++) {
		if (scrn(HX+bax[i],HY+bay[i])!=SPC) return(1);
	}
	
	for (i=0;i<BBALNS;i++) printxy2(bax[i],bay[i],bac[i]);
	
	return(0);
}

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

break_balloon()
/* 風船破裂 */
{
int i;
	if (rand2(2)) {
		if (bang_len>0) a_play(bang,bang_len,4,3,bang_len);
	} else {
		if (pon_len>0) a_play(pon,pon_len,4,3,pon_len);
	}
	
	bac[0]=BALN9;
	bac[1]=SPC;
	bac[2]=BALN9;
	bac[3]=BALN11;
	bac[4]=BALN11;
	bac[5]=BALN12;
	bac[6]=BALN13;
	bac[7]=BALN12;
	/* 後はそのまま */
	for (i=0;i<BBALNS;i++) printxy2(bax[i],bay[i],bac[i]);
}

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

int balloon_move()
/* 風船の動作 */
{
int ch,x,y;
	/* 風船の揺れ */
	m+=d;
	if (m==1||m==5) d=-d;
	
	/* キー入力 */
	ch=getky();
	if (ch==EXITCUT) return(EXITOVER); /* 強制中断 */
	if (ch==0) return(READY); /* キー入力が無かった時：なにもしない */
	
	/* 座標退避 */
	x=bx;
	y=by;
	
	switch (ch) {
		/* 移動 */
		case '8':/* 上 */
			y--;
			play_music("<C32>");
			break;
		case '2':/* 下 */
			y++;
			play_music("C32");
			break;
		case '4':/* 左 */
			x--;
			play_music("E32");
			break;
		case '6':/* 右 */
			x++;
			play_music("G32");
			break;
	}
	if (x!=bx || y!=by) { /* 動いた時 */
		if (x>=0 && x<=FWX-2 && y>=0 && y<=FWY-5) {
			/* 動ける時のみ（揺れも考慮に入れる）*/
			bx=x;
			by=y;
		}
	}
	return(READY);
}

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

int getky()
/* キー入力：複数キーの設定を可能にするため */
/* でも基本操作はテンキーで行う */
/* 一応JOYSTICK対応だよ */
{
int c,js;
int pts,pte; /* パニックタイム計測用 */
	c=inkey2(1,0);
	if (c==0) { /* not key enter */
		/* JOY STICK input */
		js=JOYGET(0)&JOYGET(1);
		if ((js&BIT3)==0) c='6';
		if ((js&BIT2)==0) c='4';
		if ((js&BIT1)==0) c='2';
		if ((js&BIT0)==0) c='8';
	}
	
	switch (c) { /* カーソルキー対応コード変換 */
		case SKleft: /* left */
			c='4';
			break;
		case SKup: /* up */
			c='8';
			break;
		case SKright: /* right */
			c='6';
			break;
		case SKdown: /* down */
			c='2';
			break;
	}
	
	c&=0xff;
	switch (c) { /* その他：特殊キー */
		case 0x0d:/* PANIC */
			time(&pts);
			curon();
			cls();
			spawnlp(P_WAIT,exec,exec,NULL,NULL);
			CRTMOD(16); // cwidth(96);
			pop_tvram();
			title();		/* タイトル表示 */
			if (fdemo==2) setumei(); /* デモ中２は説明表示 */
			if (fdemo==0) {	/* ゲーム中 */
				balns_left();	/* 残り風船数表示 */
			}
			time(&pte);
			ptime+=(pte-pts); /* パニック経過時間 */
			/* PANICの直後はPAUSEから */
		case ESC:/* PAUSE */
			time(&pts);
			curon();
			center("ＰＡＵＳＥ",EY+1);
			c=KFLUSHGC();
			center("          ",EY+1);
			curoff();
			if (c!=EXITCUT) c=0; /* 強制中断以外は無効 */
			time(&pte);
			ptime+=(pte-pts); /* パニック経過時間 */
	}
	return(c);
}

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

int play_music(unchar *mml)
/* トラック１の音楽演奏 */
{
	m_alloc(1,500);
	m_assign(1,1);
	m_trk(1,mml);
	return(m_play('NASI','NASI','NASI','NASI','NASI','NASI','NASI','NASI'));
}

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

center(unchar *mes,int y)
/* メッセージセンタリング表示 */
{
int x;
	x=(DX-strlen(mes))/2; /* センタリング */
	B_LOCATE(x,y);
	B_PRINT(mes);
}

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

message(unchar *mes,int tim)
/* メッセージを指定回数点滅表示する */
{
int i,x,y;
unchar line[DX];
	x=(DX-strlen(mes))/2; /* センタリング */
	y=HY+(EY-HY)/2;
	string(line,SPC,strlen(mes));
	for (i=0;i<tim;i++) {
		EX_COLOR(TYELLOW|HLIGHT|SHAJI); /* 黄色＋強調＋斜字 */
		B_LOCATE(x,y); 	EX_PRINT16(mes);
		vwait(22);
		EX_COLOR(TWHITE);
		B_LOCATE(x,y); 	B_PRINT(line);
		beep();
		vwait(22);
	}
}

/******************************************************************/
/* 面ロードシステム */
/******************************************************************/

int make_men(unchar *menfile)
/* 面を描く
	面の変更をし易いように、面データは外部ファイル化し、
	スタート、ゴールの位置はmake_men()ルーチンで設定することにした
	必ず、横４０＊縦２５のこと
		壁１	/	☆	8199
		壁２	=	★	819a
		壁３	.	○	819b
		壁４	,	●	819c
		壁５	@	◎	819d
		壁６	|	◇	819e
		壁７	:	◆	819f
		壁８	%	□	81a0
		壁９	$	■	81a1
		壁１０	<	△	81a2
		壁１１	>	▲	81a3
		壁１２	[	▽	81a4
		壁１３	]	▼	81a5
		壁１４	*	＊	8196
		外枠	+
		ｽﾀｰﾄﾁﾃﾝ	`	そこを左上とし、横３＊縦６の空間に風船が表示される。
				この領域を中心に、左右に２列の空きがあること。
				（風船が揺れるから。）
		ｺﾞｰﾙﾁﾃﾝ	\	ここに風船の一部が入ればゴール・インとなる
				ゴール領域を囲むだけでいい（中を埋める必要はない）
		記号以外の文字はそのまま表示する
		"スタート""ゴール"は枠内に入れること
		ただし、'ｺ' = "ゴ"になる
*/
{
FILE *fp;
unchar line[DISPX+1],token[DISPX+1];
int x,y;
	fp=fopen(menfile,"rt");
	if (fp==NULL) {
		printsn("\n\a面データが読み出せません：",menfile);
		return(1);
	}
	
	/* スタート・ゴールの位置を読み出す */
	bsx=-1;
	gl=0;
	y=HY-1;
	while (y<EY) {
		if (read1line(fp,line,token)) break;
		printxys(HX,++y,line); /* 表示 */
		for (x=HX;x<=EX;x++) {
			switch (scrn(x,y)) {
				case GOAL: /* ゴール位置 */
					if (gl<GMAX) {
						gx[gl]=x-HX;
						gy[gl++]=y-HY;
					}
					printxy(x,y,SPC); /* 印を消す */
					break;
				case START: /* スタート位置 */
					if (bsx==-1) {
						/* 最初に１点だけが有効 */
						bsx=x-HX;
						bsy=y-HY;
					}
					printxy(x,y,SPC); /* 印を消す */
					break;
			}
		}
	}
	
	fclose(fp);
	
	/* エラーチェック */
	x=0;
	if (bsx==-1) {x=1; prints("\nスタート地点がないよ！");}
	if (gl==0) {x=1; prints("\nゴール地点がないよ！");}
	if (x) { /* エラー */
		prints("\a\nという訳でゲームが出来ません。あしからず。");
		return(1);
	}
	return(0);
}

/******************************************************************/
/* 仮想ＶＲＡＭシステム */
/******************************************************************/
/* 仮想ＶＲＡＭ */

static unchar tvram[WX][WY];

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

printxy2(int x,int y,int c)
{
	printxy(HX+x,HY+y,c);
}

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

void printxy(int x,int y,int c)
/* 仮想画面と実画面変換を行う */
/* 内部処理キャラクターと表示キャラクターの変換を行う */
/* 仮想画面は48=96/2桁、31行で(0,0)-(47,30)で座標を表す */
/* 表示キャラクターは全て全角文字だから */
{
struct FNTBUF *font;
	/* 仮想テキストＶＲＡＭに出力 */
	tvram[x][y]=c;
	
	/* 座標変換 */
	/* 実座標は(0,0)-(95,30) */
	/* 最下行は使えない */
	B_LOCATE(x*2,y);
	
	/* キャラクター変換 */
	switch (c) {
		/* 半角全角変換 */
		default:
			B_PUTC(hantozen(c));
			return;
		
		/* 特殊変換 */
		case 'ｺ'   :B_PUTC(0x8353); return; /* 'ゴ' */
		case START :B_PUTC(0x8140); return; /* スタート地点 */
		case GOAL  :B_PUTC(0x8140); return; /* ゴール地点 */
		case BALN  :B_PUTC(0x818a); return; /* ♀:残り表示の風船 */
		
		/* 壁１４種類 */
		case KABE1 :B_PUTC(0x8199); return;
		case KABE2 :B_PUTC(0x819a); return;
		case KABE3 :B_PUTC(0x819b); return;
		case KABE4 :B_PUTC(0x819c); return;
		case KABE5 :B_PUTC(0x819d); return;
		case KABE6 :B_PUTC(0x819e); return;
		case KABE7 :B_PUTC(0x819f); return;
		case KABE8 :B_PUTC(0x81a0); return;
		case KABE9 :B_PUTC(0x81a1); return;
		case KABE10:B_PUTC(0x81a2); return;
		case KABE11:B_PUTC(0x81a3); return;
		case KABE12:B_PUTC(0x81a4); return;
		case KABE13:B_PUTC(0x81a5); return;
		case KABE14:B_PUTC(0x8196); return;
		
		case BALN0 :B_PUTC(0x815e); return; /* 風船構成部品０,７ */
		case BALN1 :B_PUTC(0x8150); return; /* 風船構成部品１ */
		case BALN2 :B_PUTC(0x815f); return; /* 風船構成部品２,５ */
		case BALN6 :B_PUTC(0x8151); return; /* 風船構成部品６ */
		case BALN11:B_PUTC(0x819b); return; /* 風船構成部品１１ */
		
		/* 外字変換 */
		case BALN3 : font=&f_ec56; break; /* 風船構成部品３ */
		case BALN4 : font=&f_ec57; break; /* 風船構成部品４ */
		case BALN8 : font=&f_ebea; break; /* 風船構成部品８,９ */
		case BALN10: font=&f_ebf2; break; /* 風船構成部品１０ */
		case WAKU  : font=&f_ebf6; break; /* 外枠 */
	}
	fontset(font);
	FONTPUT2(font);
}

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

printxys2(int x,int y,unchar *s)
/* 文字列表示（半角専用）*/
{
	printxys(HX+x,HY+y,s);
}

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

printxys(int x,int y,unchar *s)
/* 文字列表示（半角専用）*/
{
int i;
	for (i=0;i<strlen(s);i++) {
		printxy(x,y,s[i]);
		x++;
		if (x>=WX) {x=0; y++;}
		if (y>=WY) y=WY-1;
	}
}

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

kbox(int sx,int sy,int ex,int ey,int c)
/* 仮想画面ボックス */
{
int x,y;
	for (x=sx;x<=ex;x++) {
		printxy2(x,sy,c);
		printxy2(x,ey,c);
	}
	for (y=sy;y<=ey;y++) {
		printxy2(sx,y,c);
		printxy2(ex,y,c);
	}
}

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

int scrn(int x,int y)
/* 仮想テキストＶＲＡＭを読み出す */
{
	return(tvram[x][y]);
}

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

init_tvram()
/* 仮想テキストＶＲＡＭ初期化 */
{
int x,y;
	for (x=0;x<WX;x++) {
		for (y=0;y<WY;y++) tvram[x][y]=SPC;
	}
}

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

pop_tvram()
/* 仮想テキストＶＲＡＭ表示 */
{
int x,y;
	for (x=0;x<WX;x++) {
		for (y=0;y<WY;y++) printxy(x,y,tvram[x][y]);
	}
}

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