/*----------------------------------
  vs-shooting ver.0.00  2001.1.31
  (c) won-wan [ Tsutsumi Hiroyuki]
----------------------------------*/

#include	<stdio.h>
#include	<stdlib.h>
#include	<sys/bios.h>

#define	uchar	unsigned char

int	main();
void	g_init();
int	g_main();
void	g_start();
void	g_human();
void	g_comp();
void	g_enemy();
void	g_attack();
void	g_over();
void	g_quit();
void	v_init();
void	v_cls();
void	v_score();
void	v_spr_prt(int c,int x,int y,int p,int f);
void	v_spr_flush();
void	a_init();
void	a_play(int no);
void	a_autostop();

int	v_sprs=0;
int	v_fonts=8;
char	v_fontdata[]={
		0x18,0x18,0x18,0x3c,0x3c,0xbd,0xff,0xff,	/* human,com-attacker */
		0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x00,	/* human,com-beam */
		0xcc,0x33,0xcc,0x33,0xcc,0x33,0xcc,0x33,	/* hit-1 */
		0x33,0xcc,0x33,0xcc,0x33,0xcc,0x33,0xcc,	/* hit-2 */
		0x00,0x00,0x3c,0xff,0xa5,0xff,0x3c,0x00,	/* enemy-1 */
		0x03,0x07,0x3e,0x34,0x2c,0x7c,0xe0,0xc0,	/* enemy-2 */
		0x00,0x00,0x18,0x24,0x24,0x18,0x00,0x00,	/* enemy-bomb */
/*
		0xff,0x81,0x81,0x81,0x81,0x81,0x81,0xff,
		0x7e,0x81,0x81,0x81,0x81,0x81,0x81,0x7e,
*/
		0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
	};
enum{P_ATTACKER,P_BEAM,P_DEAD_1,P_DEAD_2,P_ENEMY_1,P_ENEMY_2,P_BOMB};
uchar	a_sin16[]={
		0xa8,0xdc,0xee,0xef,0xde,0xbc,0x9a,0x89,
		0x67,0x56,0x34,0x12,0x01,0x11,0x32,0x75
	};
uchar	a_pulse16[]={
		0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
	};
uchar	a_noko16[]={
		0xff,0xee,0xdd,0xcc,0xbb,0xaa,0x99,0x88,
		0x77,0x66,0x55,0x44,0x33,0x22,0x11,0x00
	};
enum{SE_OFF,SE_BEAM,SE_LASER,SE_HIT,SE_DEAD};
int	a_t[4];
int	t,gt,et,at;
int	key,key_old=KEY_START;
int	gf=0;
int	hi;
int	hx,hy,hf,hl,hs;
int	cx,cy,cf,cl,cs;
struct{int x,y,z,f;}	e[50],a[50],ha,ca;	/* enemy,enemy-attack,human-attack,comp-attack */

char	s[256];
int	i,j;


int main()
{
	v_init();		/* init screen */
	a_init();		/* init sound */
	g_init();
	while(g_main());
	g_quit();
	return(0);
}

void g_init()
{
	t=sys_get_tick_count();
	gt=t;
	gf=0;
	hi=0;hs=0;hl=0;
	v_score();
	while((key_old=key_press_check())&KEY_A);
}

int g_main()
{
	key=key_press_check();
	if((key&KEY_START)&&(key_old==0))return(0);
	if(gf>0){	/* play */
		if(gf&1)g_human();
		if(gf&2)g_comp();
		if(gf&4)g_enemy();
		if(gf&4)g_attack();
		if(!(gf&2))text_put_string(5,0,"-- DEAD --");
		if(!(gf&1)){
			text_put_string(5,8,"GAME OVER");
			if((key&KEY_A)&&(key_old==0)){gf=0;v_cls();}
		}
	}else{		/* title */
		text_put_string(2,8,"push 'A' button");
		text_put_string(9,9,"to start.");
		if((key&KEY_A)&&(key_old==0))g_start();
	}
	v_score();
	v_spr_flush();
	while((t=sys_get_tick_count())-gt<2);gt=t;
	a_autostop();
	key_old=key;
	return(1);
}

void g_start()
{
	gf=7;
	et=t;at=t;
	hs=0;hl=3;hx=0;hy=144-8;
	cs=0;cl=3;cx=160-8;cy=0;
	for(i=0;i<50;i++){
		e[i].x=0;e[i].y=0;e[i].z=0;e[i].f=0;
		a[i].x=0;a[i].y=0;a[i].z=0;a[i].f=0;
	}
	v_cls();
	v_score();
}

void g_human()
{
	if(hf>0){
		if(key&KEY_RIGHT1)if(hx<152)hx+=4;
		if(key&KEY_LEFT1)if(hx>0)hx-=4;
		if(key&KEY_A)if(ha.f==0){ha.f=1;ha.x=hx;ha.y=hy;a_play(SE_BEAM);}
		v_spr_prt(P_ATTACKER,hx,hy,4,0);
	}else{
		if(hf<0){
			v_spr_prt(hf&4?P_DEAD_1:P_DEAD_2,hx,hy,4,0);
		}else{
			if(hl==0){g_over();return;}
			hl--;
		}
		hf++;
	}
	if(ha.f>0){
		for(i=0;i<50;i++){							/* hit ? */
			if((e[i].f>0)&&(e[i].x<ha.x+8)&&(e[i].x>ha.x-8)&&(e[i].y<ha.y+8)&&(e[i].y>ha.y-8)){
				if(ha.f==1)hs+=10;
				if(ha.f==2)hs+=50;
				e[i].f=0;
				ha.f=0;
				a_play(SE_HIT);
			}
		}
		if((cf>0)&&(ha.x<cx+8)&&(ha.x>cx-8)&&(ha.y<cy+8)&&(ha.y>cy-8)){		/* comp die */
			ha.f=0;
			cf=-100;
		}

	}
	if(ha.f>0){
		ha.y-=5;
		if(ha.y<-2)ha.f=0;
		v_spr_prt(P_BEAM,ha.x,ha.y,4,0);
	}
}

void g_comp()
{
	static	rk=0;
	int	r=rand()%100;
	if(cf>0){
		if(r<8)rk=r;
		if(rk&1)if(cx<152)cx+=4;
		if(rk&2)if(cx>0)cx-=4;
		if(rk&4)if(ca.f==0){ca.f=1;ca.x=cx;ca.y=cy;}
		v_spr_prt(P_ATTACKER,cx,cy,4,CFM_FLIP_V|CFM_FLIP_H);
	}else{
		if(cf<0){
			v_spr_prt(cf&4?P_DEAD_1:P_DEAD_2,cx,cy,4,CFM_FLIP_V|CFM_FLIP_H);
		}else{
			if(cl==0){gf&=5;return;}
			cl--;
		}
		cf++;
	}
	if(ca.f>0){
		for(i=0;i<50;i++){							/* hit ? */
			if((e[i].f>0)&&(e[i].x<ca.x+8)&&(e[i].x>ca.x-8)&&(e[i].y<ca.y+8)&&(e[i].y>ca.y-8)){
				if(ha.f==1)cs+=10;
				if(ha.f==2)cs+=50;
				e[i].f=0;
				ca.f=0;
			}
		}
		if((hf>0)&&(ca.x<hx+8)&&(ca.x>hx-8)&&(ca.y<hy+8)&&(ca.y>hy-8)){		/* human die */
			ca.f=0;
			hf=-100;
			a_play(SE_DEAD);
		}
	}
	if(ca.f>0){
		ca.y+=5;
		if(ca.y>142)ca.f=0;
		v_spr_prt(P_BEAM,ca.x,ca.y,4,CFM_FLIP_V|CFM_FLIP_H);
	}
}

void g_enemy()
{
	if(t-et>5){
		et=t;
		for(i=0;i<50;i++){
			if(e[i].f==0){
				if(rand()%100<5){		/* create enemy-1 */
					e[i].f=1;
					e[i].z=rand()%2;
					e[i].x=e[i].z==0?-8:160;
					e[i].y=(rand()%14+2)*8;
					for(j=0;j<50;j++){
						if(i==j)continue;
						if((e[j].f!=e[i].f)||(e[j].x!=e[i].x)||(e[j].y!=e[i].y))continue;
						e[i].f=0;
					}
				}else if(rand()%100<1){		/* create enemy-2 */
					e[i].f=2;
					e[i].z=rand()%4+4;
					e[i].x=e[i].z<6?-8:160;
					e[i].y=(rand()%10+4)*8;
					for(j=0;j<50;j++){
						if(i==j)continue;
						if((e[j].f!=e[i].f)||(e[j].x!=e[i].x))continue;
						e[i].f=0;
					}
				}
			}
			if(e[i].f==1){				/* move enemy-1 */
				if(e[i].z==0)e[i].x+=2;
				if(e[i].z==1)e[i].x-=2;
				if((e[i].x<-6)||(e[i].x>158))e[i].f=0;
			}else if(e[i].f==2){			/* move enemy-2 */
				if(rand()%100<20)e[i].z^=1;
				if(rand()%100<5)e[i].z^=2;
				if(e[i].z==4){e[i].x+=3;e[i].y+=2;}
				if(e[i].z==5){e[i].x-=3;e[i].y-=2;}
				if(e[i].z==6){e[i].x+=3;e[i].y-=2;}
				if(e[i].z==7){e[i].x-=3;e[i].y+=2;}
				if((e[i].x<-6)||(e[i].x>158)||(e[i].y<-2)||(e[i].y>142))e[i].f=0;
			}

		}
	}
	for(i=0;i<50;i++)if(e[i].f>0){					/* die ? */
		if((hf>0)&&(e[i].x<hx+8)&&(e[i].x>hx-8)&&(e[i].y<hy+8)&&(e[i].y>hy-8)){
			e[i].f=0;
			hf=-100;
			a_play(SE_DEAD);
		}
		if((cf>0)&&(e[i].x<cx+8)&&(e[i].x>cx-8)&&(e[i].y<cy+8)&&(e[i].y>cy-8)){
			e[i].f=0;
			cf=-100;
		}
	}
	for(i=0;i<50;i++){					/* display */
		if(e[i].f==1)v_spr_prt(P_ENEMY_1,e[i].x,e[i].y,4,0);
		if(e[i].f==2)v_spr_prt(P_ENEMY_2,e[i].x,e[i].y,4,e[i].z&2?0:CFM_FLIP_H);
	}
}

void g_attack()
{
	if(t-at>7){
		at=t;
		for(i=0;i<50;i++){
			if(e[i].f==1)if(rand()%100<1){		/* create enemy-1-attack */
				for(j=0;j<50;j++)if(a[j].f==0){
					a[j].f=1;
					a[j].z=rand()%2;
					a[j].x=e[i].x;
					a[j].y=e[i].y;
					break;
				}
			}
		}
		for(i=0;i<50;i++){
			if(a[i].f==1){				/* move enemy-1-attack */
				if(a[i].z==0)a[i].y+=4;
				if(a[i].z==1)a[i].y-=4;
				if((a[i].y<-2)||(a[i].y>142))a[i].f=0;
			}
		}
	}
	for(i=0;i<50;i++)if(a[i].f>0){					/* die ? */
		if((hf>0)&&(a[i].x<hx+8)&&(a[i].x>hx-8)&&(a[i].y<hy+8)&&(a[i].y>hy-8)){
			a[i].f=0;
			hf=-100;
			a_play(SE_DEAD);
		}
		if((cf>0)&&(a[i].x<cx+8)&&(a[i].x>cx-8)&&(a[i].y<cy+8)&&(a[i].y>cy-8)){
			a[i].f=0;
			cf=-100;
		}
	}
	for(i=0;i<50;i++){					/* display */
		if(a[i].f==1)v_spr_prt(P_BOMB,a[i].x,a[i].y,4,0);
	}
}

void g_over()
{
	gf&=6;
	if(hs>hi)hi=hs;
}

void g_quit()
{
}

void v_init()
{
	text_set_screen(SCREEN1);
	text_screen_init();
	sprite_set_range(0,0);
	sprite_set_window(0,0,160,144);
	font_set_monodata(0,v_fonts,v_fontdata);
	display_control(DCM_SCR1|DCM_SPR|DCM_SPR_WIN|DCM_SCR2_WIN_INSIDE);
}

void v_cls()
{
	text_screen_init();
}

void v_score()
{
	sprintf(s,"vs-");	text_put_string(20,0,s);
	sprintf(s,"shooting");	text_put_string(20,1,s);
	sprintf(s,"Hi-SCORE");	text_put_string(20,5,s);
	sprintf(s,"%06d",hi);	text_put_string(22,6,s);
	sprintf(s,"SCORE");	text_put_string(23,8,s);
	sprintf(s,"%06d",hs);	text_put_string(22,9,s);
	sprintf(s,"LEFT");	text_put_string(24,12,s);
	sprintf(s,"%02d",hl);	text_put_string(26,13,s);
	if(key&KEY_B){
		text_put_string(20,16,"ver.0.00");
		text_put_string(20,17,"01.01.31");
	}else{
		text_put_string(20,16,"(c)2001 ");
		text_put_string(20,17," won-wan");
	}
}

void v_spr_prt(int c,int x,int y,int p,int f)
{
	p=(p&7)<<9;
	sprite_set_char_location(v_sprs++,c|p|f,x,y);
}

void v_spr_flush()
{
	sprite_set_range(0,v_sprs);
	v_sprs=0;
}

void a_init()
{
	sound_init();
	sound_set_output(0x0f);
	sound_set_channel(0xef);
}

void a_play(int no)
{
	/* f=3.072*106/((2048-pitch)*32) Hz */
	/* ch0.normal ch1.voice ch2.sweep ch3.noise */
	switch(no){
		case SE_OFF:{
			a_t[0]=0;a_t[1]=0;a_t[2]=0;a_t[3]=0;
			break;
		}
		case SE_BEAM:{
			sound_set_wave(0,a_noko16);
			sound_set_pitch(0,1850);
			sound_set_volume(0,200);
			a_t[0]=2;
			break;
		}
		case SE_LASER:{
			sound_set_wave(0,a_sin16);
			sound_set_pitch(0,1000);
			sound_set_volume(0,255);
			a_t[0]=5;
			break;
		}
		case SE_HIT:{
			sound_set_wave(2,a_pulse16);
			sound_set_pitch(2,1000);
			sound_set_sweep(100,5);
			sound_set_volume(2,255);
			a_t[2]=5;
			break;
		}
		case SE_DEAD:{
			sound_set_wave(3,a_sin16);
			sound_set_pitch(3,1000);
			sound_set_noise(8);
			sound_set_noise(16);
			sound_set_volume(3,255);
			a_t[3]=10;
			break;
		}
	}
}

void a_autostop()
{
	int	i;
	for(i=0;i<4;i++){
		if(a_t[i]>0)a_t[i]--;
		if(a_t[i]==0)sound_set_volume(i,0);
	}
}
