/*                                                   */
/* othello game     file name: othello.c             */
/*                                                   */
/*           programed by K. Shishido                */
/*           compiler: LSI-C                         */
/*               date: 2000.12.12.                   */
/*                                                   */

#include <stdio.h>
#include <stdlib.h>
#include <sys/bios.h>
#include <string.h>
#include "othello.h"
#define ERR 27

static OTH_DATA	oth_data;
static RS_DATA	rs_data;
static unsigned int	g_mm[32], g_mc[32];
static unsigned int	g_msg[256];
static intvector_t far g_iv, far g_liv;
static int	dummy;

void far iv_routine(void){
	rs_data.buffer[rs_data.bottom++]= comm_receive_char();
	rs_data.buffer[rs_data.bottom]= 0;
	if(rs_data.bottom >= BUFFSIZE){
		rs_data.bounds= TRUE; /* 未使用変数 */
		rs_data.bottom= 0;
	}
	return ;
}

void comm_init(void){
	comm_close();
	rs_data.top= rs_data.bottom= 0;
	rs_data.sequence= 0;
	rs_data.bounds= rs_data.progress= FALSE;
	rs_data.totaltimeout= 20;
	comm_set_baudrate(COMM_SPEED_38400);
	comm_open();
	comm_set_timeout( 3, 6);
	g_iv.callback= (void (near *)())(unsigned int)(iv_routine);
	g_iv.cs= _CS;
	g_iv.ds= _DS;
	sys_interrupt_set_hook(SYS_INT_RECEIVEREADY, &g_iv, &g_liv);
/*	sys_interrupt_set_hook(SYS_INT_RECEIVEREADY, &g_iv, NULL); */
	return ;
}

void comm_terminate(void){
	sys_interrupt_reset_hook(SYS_INT_RECEIVEREADY, NULL);
	comm_close();
	return ;
}

void cls(int screen){
	screen_fill_char(screen, 0, 0, 32, 32, (4 << 9) | 0);
}

void clear_msg_line(int line){
	screen_fill_char(0, 17, line, 14, 1, (0 << 9) | 0);
}

void clear_msg_area(void){
	screen_fill_char(0, 17, 2, 14, 10, (0 << 9) | 0);
}

void set_fonts(void){
	int		s;
	lcd_set_color(0x5320, 0xfca7);
	palette_set_color( 0, 0x5430);
	palette_set_color( 4, 0x7530);
	palette_set_color( 5, 0x7500);
	palette_set_color(12, 0x7530);
	palette_set_color(13, 0x7530);

	font_set_colordata( 0,  1, bmp_null);
	font_set_colordata( 1,  7, bmp_base);
	font_set_colordata( 8,  4, bmp_cursor);
	font_set_colordata(12,  4, bmp_black);
	font_set_colordata(16,  4, bmp_white);
	font_set_colordata(20, 12, bmp_invert);

	sprite_set_range(0, 4);
	s= S2PR | (4 << 9) | 8;
	sprite_set_char(0, s);
	sprite_set_char(1, s+ 1);
	sprite_set_char(2, s+ 2);
	sprite_set_char(3, s+ 3);
	return ;
}

int is_sjis1(unsigned char c){
	return c > 0x80 && c < 0xa0 || c >= 0xe0 && c < 0xfd ;
}

int is_sjis2(unsigned char c){
	return c >= 0x40 && c < 0xfd && c != 0x7f ;
}

void draw_text(int screen, int x, int y, unsigned int d){
	screen_set_char(screen, x, y, g_mc[d], 1, (void far *)&g_msg[g_mm[d]]);
}

void mk_msg2(int index, char far *tx){
	static unsigned char font[8];
	static int	c= 0;
	int		moji, i= 0;

	g_mm[index]= c;
	while(*tx != 0){
		if(is_sjis1(*tx)){
			moji= *(tx++) << 8 | *tx;
			text_get_fontdata(moji, font);
		}
		else{
			text_get_fontdata(*tx, font);
		}
		font_set_monodata(0x80+ c, 1, (void far *)font);
		g_msg[c]= (4 << 9) | 0x80+ c;
		tx++;
		c++;
		i++;
	}
	g_mc[index]= i;
	return ;
}

int mk_msg(int index, char far *tx){
	static unsigned char font[8];
	int		moji, i= 0;

	while(*tx != 0){
		if(is_sjis1(*tx)){
			moji= *(tx++) << 8 | *tx;
			text_get_fontdata(moji, font);
		}
		else{
			text_get_fontdata(*tx, font);
		}
		font_set_monodata(0x80+ g_mm[index]+ i, 1, (void far *)font);
		g_msg[(g_mm[index]+ i)]= (4 << 9) | (0x80+ g_mm[index]+ i);
		tx++;
		i++;
	}
	return index;
}

void set_msg(void){
	static char	far *tx[]= {
		"対戦オセロゲーム",			/* message  0 */
		"黒：",						/* message  1 */
		"白：",						/* message  2 */
		"先攻ですか？",				/* message  3 */
		"Ａ：はい",					/* message  4 */
		"Ｂ：いいえ",				/* message  5 */
		"あなたは黒です。",			/* message  6 */
		"あなたは白です。",			/* message  7 */
		"再ゲームします？",			/* message  8 */
		"Ｂ：終了",					/* message  9 */
		"拒否されました。",			/* message 10 */
		"　　",						/* message 11 */
		"　　",						/* message 12 */
		"そこは置けません。",		/* message 13 */
		"置く所がありません。",		/* message 14 */
		"Ａ：はじめから",			/* message 15 */
		"Ａ：パス",					/* message 16 */
		"あなたの勝ちです。",		/* message 17 */
		"あなたの負けです。",		/* message 18 */
		"引き分けです。",			/* message 19 */
		"Ｂ：キャンセル",			/* message 20 */
		"終了します？",				/* message 21 */
		"応答待ち．．．  ",			/* message 22 */
		"ゲーム中止要求",			/* message 23 */
		"通信異常発生",				/* message 24 */
		"強制終了されました。",		/* message 25 */
		"相手はパスです。",			/* message 26 */
		"            ",				/* message 27 */
		""							/* end of message */
	} ;
	int		i= 0;

	while(strlen(tx[i])) mk_msg2(i++, tx[i]);
	return ;
}

void move_cursor(int sp, int x, int y){
	sprite_set_location(sp   , x* 16,    y* 16+ 16);
	sprite_set_location(sp+ 1, x* 16+ 8, y* 16+ 16);
	sprite_set_location(sp+ 2, x* 16,    y* 16+ 24);
	sprite_set_location(sp+ 3, x* 16+ 8, y* 16+ 24);
	return ;
}

void set_sprite(int k){
	int		s;
	k = k* 4+ 20;
	s= ~S2PR & ((5 << 9) | k);
	sprite_set_char(4, s);
	sprite_set_char(5, s+ 1);
	sprite_set_char(6, s+ 2);
	sprite_set_char(7, s+ 3);
	return ;
}

void clear_chip(int x, int y){
	screen_fill_char(1, x* 2, y* 2+ 2, 2, 2, (4 << 9) | 0);
}

void chip_locate(int bw, int x, int y){
	static unsigned int	d[4];
	int		i;

	for(i= 0; i< 4; i++)
		d[i]= (5 << 9) | ((bw)? 12: 16)+ i;
	screen_set_char(1, x* 2, y* 2+ 2, 2, 2, (void far *)d);
	return ;
}

void chip_replace(int bw, int x, int y){
	int		k, dr, c= 2;

	if(bw) k= 2, dr= -1;
	else k= 0, dr= 1;

	sprite_set_range(4, 4);
	clear_chip(x, y);
	do {
		set_sprite(k);
		move_cursor(4, x, y);
		k += dr;
		sys_wait(9);
	} while(c--) ;
	chip_locate(bw, x, y);
	sprite_set_range(0, 4);
	return ;
}

void draw_base(void){
	char	num[3];
	int		x, y;
	static int	d= (0<<9) | 7;
	static int	d1[4]= { (0<<9) | 1, (0<<9) | 2, (0<<9) | 3, (0<<9) | 4} ;
	static int	d2[2]= { (0<<9) | 6, (0<<9) | 6} ;
	static int	d3[2]= { (0<<9) | 5, (0<<9) | 5} ;

	cls(0);
	cls(1);
	for(y= 0; y< 8; y++)
		for(x= 0; x< 8; x++) oth_data.board[x][y]= -1;
	for(x= 0; x< 8; x++)
		screen_set_char(0, x * 2, 1, 2, 1, (void far *)d3);
	screen_set_char(0, 16, 1, 1, 1, (void far *)&d);
	for(y= 0; y< 8; y++){
		for(x= 0; x< 8; x++)
			screen_set_char(0, x * 2, y * 2+ 2, 2, 2, (void far *)d1);
		screen_set_char(0, 16, y * 2+ 2, 1, 2, (void far *)d2);
	}
	draw_text(0, 18,  1, 0);
	draw_text(0, 18, 16, 1);
	draw_text(0, 23, 16, 2);
	chip_locate(BLACK, 3, 3);
	chip_locate(BLACK, 4, 4);
	chip_locate(WHITE, 3, 4);
	chip_locate(WHITE, 4, 3);
	oth_data.board[3][3]= oth_data.board[4][4]= BLACK;
	oth_data.board[3][4]= oth_data.board[4][3]= WHITE;
	oth_data.b_count= oth_data.w_count= 2;
	oth_data.x= oth_data.y= 3;
	sprintf(num, "%2d", 2);
	draw_text(0, 20, 16, mk_msg(11, num));
	draw_text(0, 25, 16, mk_msg(12, num));
	move_cursor(0, oth_data.x, oth_data.y);
	return ;
}

void wb_select(void){
	display_control(display_status() & ~SPR);
	clear_msg_area();
	draw_text(0, 19, 4, 3);
	draw_text(0, 19, 7, 4);
	draw_text(0, 19, 8, 5);
	oth_data.active= FALSE;
	oth_data.cntl= VS;
	return ;
}

void go_next(void){
	display_control(display_status() & ~SPR);
	draw_text(0, 18, 6, 8);
	draw_text(0, 18, 8, 15);
	draw_text(0, 18, 9, 9);
	oth_data.cntl= NXT;
	return ;
}

int chip_check(int bw, int xx, int yy){
	static int		dx[8]= {  1,  1,  0, -1, -1, -1,  0, 1} ;
	static int		dy[8]= {  0, -1, -1, -1,  0,  1,  1, 1} ;
	int		x, y, i;
	int		mask, f, bd;

	oth_data.bc= 0x0;
	if(oth_data.board[xx][yy] >= 0) return 0;

	for(i= 0, mask= 0x01; i< 8; i++, mask <<= 1){
		f= FALSE;
		if((dx[i] == 1 && xx > 5) || (dx[i] == -1 && xx < 2)) continue ;
		if((dy[i] == 1 && yy > 5) || (dy[i] == -1 && yy < 2)) continue ;
		x= xx+ dx[i];
		y= yy+ dy[i];
		if(oth_data.board[x][y] == !bw){
			do {
				x += dx[i];
				y += dy[i];
				if((bd= oth_data.board[x][y]) == -1) break;
				else if(bd == bw) f= TRUE;
				if((dx[i] == 1 && x >= 7) || (dx[i] == -1 && x <= 0)) break ;
				if((dy[i] == 1 && y >= 7) || (dy[i] == -1 && y <= 0)) break ;
			} while(!f) ;
		}
		if(f) oth_data.bc |= mask;
	}
	return oth_data.bc;
}

void reversi(int bw, int xx, int yy){
	static signed int		dx[8]= {  1,  1,  0, -1, -1, -1,  0, 1} ;
	static signed int		dy[8]= {  0, -1, -1, -1,  0,  1,  1, 1} ;
	unsigned int	mask, jg;
	int		i, x, y;
	char	num[3];

	chip_locate(bw, xx, yy);
	oth_data.board[xx][yy]= bw;
	if(bw == BLACK){
		oth_data.b_count++;
		sprintf(num, "%2d", oth_data.b_count);
		draw_text(0, 20, 16, mk_msg(11, num));
	}
	else{
		oth_data.w_count++;
		sprintf(num, "%2d", oth_data.w_count);
		draw_text(0, 25, 16, mk_msg(12, num));
	}

	jg= oth_data.bc;
	for(i= 0, mask= 0x01; i< 8; i++, mask <<= 1){
		if(mask & jg){
			x= xx + dx[i];
			y= yy + dy[i];
			do{
				oth_data.board[x][y]= bw;
				chip_replace(bw, x, y);
				if(bw == BLACK){
					oth_data.b_count++;
					oth_data.w_count--;
				}
				else {
					oth_data.b_count--;
					oth_data.w_count++;
				}
				sprintf(num, "%2d", oth_data.b_count);
				draw_text(0, 20, 16, mk_msg(11, num));
				sprintf(num, "%2d", oth_data.w_count);
				draw_text(0, 25, 16, mk_msg(12, num));
				x += dx[i];
				y += dy[i];
			}
			while(oth_data.board[x][y] != bw) ;
		}
	}
	return ;
}

BOOL pass_check(int bw){
	int		i, j;

	for(j= 0; j< 8; j++)
		for(i= 0; i< 8; i++)
			if(chip_check(bw, i, j)) return FALSE;
	return TRUE;
}

BOOL pass_check2(void){
	int		k;

	for(k= 0; k< 2; k++)
		if(!pass_check(k)) return FALSE;
	return TRUE;
}

int game_end_check(void){
	int		bw;

	if((oth_data.b_count + oth_data.w_count) == 64 || pass_check2()) {
		if(oth_data.b_count > oth_data.w_count){
			if(oth_data.bw == BLACK) bw= 17;
			else bw= 18;
		}
		else if(oth_data.b_count < oth_data.w_count){
			if(oth_data.bw == WHITE) bw= 17;
			else bw= 18;
		}
		else {
			bw= 19;
		}
		clear_msg_line(4);
		draw_text(0, 18, 4, bw);
		return 1;
	}
	return 0;
}

long atol(char *bb){
	int		radix= 10;
	long	a= 0, s= 1;
	BOOL	f= FALSE;
	char	*b;

	b= bb;
	while((*b == SPC || *b == TAB) && *b != 0) b++;
	if(!strncmp(b, "0x", 2)){
		radix = 0x10;
		b++;
		f= TRUE;
	}
	else if(*b == '-'){
		s= -1;
	}
	b++;
	while(*b != 0){
		a *= radix;
		if(*b >= '0' && *b <= '9'){
			a += (*b - '0');
		}
		else if(f){
			(*b) |= 0x20;
			if(*b >= 'a' && *b <= 'f'){
				a += (*b - 'a'+ 10);
			}
			else{
				a= 0;
				break ;
			}
		}
		else{
			a= 0;
			break ;
		}
		b++;
	}
	return s * a;
}

int msg_check(char *bb){
	unsigned long	seq, rctl, dt, sum;
	unsigned char	*st, csum;
	int		i;
	static char	buf[32], *b, *bf, tmp[10];

	b= buf;
	bf= bb;
	strcpy(b, bb);
	while(*b != 0x02){
		b++;
		bf++;
		if(!(*b)) return 2;
	}
	st= (unsigned char *)bf;
	b++;
	bf++;
	if(strlen(b) != 17) return 3;
	if(strncmp(b, "WS", 2)) return 4;
	b += 2;
	if(*(b + 4) != '.') return 5;
	*(b + 4)= 0;
	seq= atol(b);
	b += 5;
	if(*(b + 2) != '.') return 6;
	*(b + 2)= 0;
	sprintf(tmp, "0x%s", b);
	rctl= atol(tmp);
	b += 3;
	if(*(b + 4) != 0x03) return 7;
	*(b + 4)= 0;
	sprintf(tmp, "0x%s", b);
	dt= atol(tmp);
	b += 5;
	sprintf(tmp, "0x%s", b);
	csum= atol(tmp);

	for(i= 0, sum= 0; i< 15; i++, st++) sum += *st;
/*	if(csum != (unsigned char)(0x000000ff & sum)) return 1; */
	if(csum != 0 && csum != (unsigned char)(0x000000ff & sum)) return 1;
	oth_data.rctl= rctl;
	if(rctl == ACK){
		if(rs_data.sequence != seq) return 8;
		rs_data.sequence++;
		return 0;
	}
	else if(rctl == SEQ || (rs_data.r_seq + 1) == seq){
		oth_data.dt= dt;
		rs_data.r_seq= seq;
		return 0;
	}
	else if(rs_data.r_seq == seq){
		return -1;
	}
	return 9;
}

int comm_msg_send(int ctl){
	int		i;
	unsigned long	sum;
	static char	*s, sbuf[20], ss[20];

	rs_data.progress= TRUE;
	s= "%cWS%04d.%02x.%04x%c";
	switch (ctl){
	case LOC:
		s= "%cWS%04d.%02x.%02x%02x%c";
		sprintf(ss, s, 0x2, rs_data.sequence, ctl, oth_data.x, oth_data.y, 0x3);
		break ;
	case RE:
	case NXT:
		sprintf(ss, s, 0x2, rs_data.sequence, ctl, oth_data.dt, 0x3);
		break ;
	case VS:
		sprintf(ss, s, 0x2, rs_data.sequence, ctl, oth_data.bw, 0x3);
		break ;
	case ACK:
		rs_data.progress= FALSE;
		sprintf(ss, s, 0x2, rs_data.r_seq, ctl, 0, 0x3);
		break ;
/*				使用中止（タイムアウトのみで対応）
	case NAK:
		rs_data.progress= FALSE;
		sprintf(ss, s, 0x2, rs_data.r_seq + 1, ctl, oth_data.dt, 0x3);
		break ;
*/
	case SEQ:
	case PAS:
	case STP:
	case ESC:
		sprintf(ss, s, 0x2, rs_data.sequence, ctl, 0, 0x3);
		break ;
	default:
		return 0;
	}
	s= ss;
	for(i= 0, sum= 0; i< 15; i++, s++) sum += (char)(*s);
	sprintf(sbuf, "%s%02x", ss, (0x000000ff & sum));
	comm_send_string(sbuf);
	comm_send_char(0x0d);		/* なぜ？send_stringでは0x0dが送れない？ */
	rs_data.timeoutcount= ODTMOUT;
	return 1;
}

int receive_ack(void){

	rs_data.progress= FALSE;
	if(oth_data.cntl == LOC && oth_data.active){
		oth_data.active= FALSE;
		reversi(oth_data.bw, oth_data.x, oth_data.y);
		display_control(display_status() & ~SPR);
		draw_text(0, 18, 4, 22);
		if(game_end_check()) go_next();
	}
	else if(oth_data.cntl == NXT){
		if(oth_data.dt) return 1;

		draw_base();
		display_control(display_status() & ~SPR);
		wb_select();
	}
	else if(oth_data.cntl == PAS){
		clear_msg_area();
	}
	else if(oth_data.cntl == STP){
		clear_msg_line(8);
		draw_text(0, 18, 7, 22);
	}
	else if(oth_data.cntl == RE){
		clear_msg_area();
		if(!oth_data.dt) return 1;
		oth_data.cntl= oth_data.bcon;
	}
	else if(oth_data.cntl == VS){
		clear_msg_area();
		if(oth_data.bw){
			oth_data.active= TRUE;
			display_control(display_status() | SPR);
			draw_text(0, 18, 14, 6);
		}
		else{
			oth_data.active= FALSE;
			display_control(display_status() & ~SPR);
			draw_text(0, 18,  4, 22);
			draw_text(0, 18, 14,  7);
		}
		oth_data.cntl= LOC;
	}
	return 0;
}

void comm_sync_wait(void){
	int		i, b;
	int		f1, f2;
	unsigned long	sys_b= 0, key_s;
	static char		buf[128];
	int			d;

	draw_text(0, 18, 4, 22);
	rs_data.timeoutcount= 200;
	comm_msg_send(SEQ);
	i= 0;
	f1= f2= FALSE;
	while(FOREVER){
		if(sys_b != sys_get_tick_count()){
			sys_b = sys_get_tick_count();
			if(rs_data.timeoutcount) rs_data.timeoutcount--;
		}
		if((key_s= key_press_check()) & KEY_START){
			bios_exit();
		}
		if(rs_data.top != rs_data.bottom){
			b= i;
			buf[i++]= rs_data.buffer[rs_data.top++];
			if(rs_data.top >= BUFFSIZE){
				rs_data.bounds= FALSE;		/* 現在未使用 */
				rs_data.top= 0;
			}
			buf[i]= 0;
			if(i >= 127){
				sprintf(buf, "buff full");
				draw_text(0, 18, 14, mk_msg(ERR, buf));
				i = 0;
				continue ;
			}
		}
		if((buf[b] == 0x0d)){				/* data receive */
			buf[b]= 0;
			if(!(d= msg_check(buf))){
				if(oth_data.rctl == SEQ){
					comm_msg_send(ACK);
					f1= TRUE;
				}
				else if(oth_data.rctl == ACK){
					f2= TRUE;
				}
				i= 0;
			}
		}
		if(f1 && f2){
			rs_data.timeoutcount= ODTMOUT;
			rs_data.totaltimeout= 20;
			rs_data.progress= FALSE;
			break ;
		}
		if(!rs_data.timeoutcount && !f2){		/* timeout occured */
			rs_data.timeoutcount= 80+ (rand() % 100);
			comm_msg_send(SEQ);
			i= 0;
		}
	}
}

int comm_rcv_control(int ctl){
	int		x, y;

	switch (ctl){
	case SEQ:
		comm_sync_wait();
		break ;
	case LOC:
		x= oth_data.dt >> 8;
		y= 0x00ff & oth_data.dt;
		display_control(display_status() | SPR);
		clear_msg_line(4);
		if(chip_check(!oth_data.bw, x, y)) reversi(!oth_data.bw, x, y);

		if(pass_check(oth_data.bw)){
			oth_data.active= FALSE;
			if(oth_data.cntl == STP){
				oth_data.bcon= PAS;
			}
			else{
				oth_data.cntl= PAS;
			}
			display_control(display_status() & ~SPR);
			draw_text(0, 18, 4, 14);
			draw_text(0, 18, 6, 16);
		}
		else{
			oth_data.active= TRUE;
			if(oth_data.cntl == STP){
				oth_data.bcon= LOC;
			}
			else{
				oth_data.cntl= LOC;
			}
			oth_data.x= x;
			oth_data.y= y;
			move_cursor(0, oth_data.x, oth_data.y);
		}
		if(game_end_check()){
			go_next();
			return 0;
		}
		break ;
	case PAS:
		draw_text(0, 18, 4, 26);
		oth_data.active= TRUE;
		display_control(display_status() | SPR);
		break ;
	case NXT:
		if(!oth_data.dt){
			draw_base();
			wb_select();
		}
		else{
			return 1;
		}
		break ;
	case RE:
		if(!oth_data.dt) return 1;

		draw_text(0, 18, 4, 10);
		clear_msg_line(5);
		clear_msg_line(7);
		oth_data.cntl= oth_data.bcon;
		break ;
/*				使用中止（タイムアウトのみで対応）
	case NAK:
		if((rs_data.r_seq+ 1) != rs_data.sequence){
			comm_msg_send(oth_data.cntl);
		}
		break ;
*/
	case STP:
		if(oth_data.cntl == STP){
			oth_data.cntl= RE;
			oth_data.dt= 0;
			comm_msg_send(oth_data.cntl);
		}
		else{
			draw_text(0, 18, 5, 23);
			draw_text(0, 18, 7, 4);
			draw_text(0, 18, 8, 20);
			oth_data.bcon= oth_data.cntl;
			oth_data.cntl= RE;
		}
		break ;
	case VS:
		oth_data.bw= !(oth_data.dt);
		clear_msg_area();
		if(oth_data.bw){
			oth_data.active= TRUE;
			display_control(display_status() | SPR);
			draw_text(0, 18, 14, 6);
		}
		else{
			oth_data.active= FALSE;
			draw_text(0, 18, 4, 22);
			draw_text(0, 18, 14, 7);
		}
		oth_data.cntl= oth_data.bcon= LOC;
		break ;
	case ESC:
		draw_text(0, 18, 4, 25);
		key_wait();
		bios_exit();

	default:
		break ;
	}
	return 0;
}

int comm_transmit(void){
	static char		buf[64];
	static int		i= 0, b= 0;
	int			d;

	if(rs_data.top != rs_data.bottom){
		buf[i]= rs_data.buffer[rs_data.top++];
		if(rs_data.top >= BUFFSIZE){
			rs_data.bounds= FALSE; /* 現在未使用 */
			rs_data.top= 0;
		}
		b= i;
		if(i++ > 127){
			sprintf(buf, "buff full");
			mk_msg(ERR, buf);
			draw_text(0, 18, 13, ERR);
			i= 0;
		}
	}
	if(buf[b] == 0x0d){						/* data receive */
		buf[b]= 0;
		if(!(d= msg_check(buf))){
			if(oth_data.rctl == ACK){
				if(receive_ack()) return 1;
				rs_data.totaltimeout= 20;
			}
			else{
				comm_msg_send(ACK);
				if(comm_rcv_control(oth_data.rctl)) return 1;
			}
		}
		else if(d == -1){
			comm_msg_send(ACK);
		}
		i= 0;
	}
	if(!rs_data.timeoutcount && rs_data.progress){
		if(rs_data.totaltimeout--){
			comm_msg_send(oth_data.cntl);
			rs_data.timeoutcount= ODTMOUT+ (rand() % 25);
		}
		else{
			draw_text(0, 18, 13, 24);
			comm_sync_wait();
		}
		i= 0;
	}
	return 0;
}

void press_A_key(int cntl){

	if(cntl == VS){
		oth_data.bw= BLACK;
	}
	else if(cntl == PAS || cntl == NXT || cntl == STP || cntl == RE){
		oth_data.dt= 0;
	}
	else if(oth_data.active){
		if(!chip_check(oth_data.bw, oth_data.x, oth_data.y)){
			draw_text(0, 18, 4, 13);
			return ;
		}
		oth_data.cntl= LOC;
	}
	else{
		return ;
	}
	comm_msg_send(cntl);
	return ;
}

void press_B_key(int cntl){

	if(cntl == VS){
		oth_data.bw= WHITE;
	}
	else if(cntl == NXT){
		oth_data.dt= 1;
	}
	else if(cntl == STP){
		clear_msg_line(5);
		clear_msg_line(7);
		clear_msg_line(8);
		oth_data.cntl= oth_data.bcon;
		return ;
	}
	else if(cntl == RE){
		clear_msg_line(5);
		clear_msg_line(7);
		clear_msg_line(8);
		oth_data.dt= 1;
	}
	else{
		return ;
	}
	comm_msg_send(cntl);
	return ;
}

void oth_run(void){
	unsigned long	sys_b= 0, key_s, c= 50;
	BOOL			f= TRUE, bb= FALSE;
	volatile unsigned int	ctl;
	unsigned int	co= 0;

	sys_b= sys_get_tick_count();
	while(FOREVER){
		ctl= oth_data.cntl;
		if(sys_b != sys_get_tick_count()){
			sys_b= sys_get_tick_count();
			if(!c--){
				if(f) palette_set_color(12, 0x7430);
				else  palette_set_color(12, 0x1430);
				f= !f;
				c= 50;
			}
			if(co) co--;
			if(rs_data.timeoutcount) rs_data.timeoutcount--;
		}
		if(comm_transmit()) break ;
		if(!co) key_s= key_press_check();
		else	continue ;

		if(key_s & KEY_START){
			if(ctl != NXT && ctl != RE){
				if(oth_data.cntl == STP || ctl == VS){
					comm_msg_send(ESC);
					break ;
				}
				draw_text(0, 18, 5, 21);
				draw_text(0, 18, 7, 4);
				draw_text(0, 18, 8, 20);
				oth_data.bcon= ctl;
				oth_data.cntl= STP;
				co= 30;
				continue ;
			}
		}
		if(key_s & KEY_A){
			if(!rs_data.progress){
				press_A_key(ctl);
				co= 30;
			}
		}
		if(key_s & KEY_B){
			if(!rs_data.progress){
				press_B_key(ctl);
				co= 30;
			}
		}
		if(oth_data.active != TRUE) continue ;
		if(key_s & KEY_X1){
			if(oth_data.y) (oth_data.y)--, bb= TRUE;
		}
		if(key_s & KEY_X2){
			if(oth_data.x < 7) (oth_data.x)++, bb= TRUE;
		}
		if(key_s & KEY_X3){
			if(oth_data.y < 7) (oth_data.y)++, bb= TRUE;
		}
		if(key_s & KEY_X4){
			if(oth_data.x) (oth_data.x)--, bb= TRUE;
		}
		if(!bb) continue ;
		move_cursor(0, oth_data.x, oth_data.y);
		co= 20;
		bb= FALSE;
	}
}

int main(int argc, char **argv){

	display_control(SC1E | SC2E | SPRWE & ~SPR);
	set_fonts();
	set_msg();
	srand((unsigned int)sys_get_tick_count());

	comm_init();
	draw_base();
	comm_sync_wait();
	wb_select();

	oth_run();

	comm_terminate();
	bios_exit();
}

void vl_errcheck(unsigned int num){
	char	n[10];

	sprintf(n, ">%04x", num);
	draw_text(0, 18, 15, mk_msg(ERR, n));
	return ;
}

void st_errcheck(char far *s){

	draw_text(0, 18, 15, mk_msg(ERR, s));
	return ;
}
