/*
 * Copyright (c) 1983 Regents of the University of California.
 * All rights reserved. The Berkeley Software License Agreement
 * specifies the terms and conditions for redistribution.
 */
static char rcsid[] = "$Header:player2.c 12.0$";
#ifndef lint
static	char *sccsid = "@(#)player2.c	1.2 83/05/20";
#endif

#include "player.h"

#define turnfirst(buf)  (*buf == 'r' || *buf == 'l')

lost()
{
	if (scene[game].ship[player].file -> struck)
		leave(0);
	if (scene[game].ship[player].file -> captured > -1)
		leave(1);
	if (windspeed == 7)
		leave(3);
	if(scene[game].ship[player].file -> FS && (!specs[scene[game].ship[player].shipnum].rig1 || windspeed == 6))
		Write(FILES + player, 0, 230, 0);
}


acceptmove(ma, ta, af)
int ma, ta, af;
{
	register int n;
	int moved = 0;
	int full, vma, dir, ch;
	char buf[60], last = '\0';

	if (scroll >= 22) scroll = 18;
	move(scroll++, 0);
	clearline();
	printw("move (%d,%c%d): ", ma, (af ? '\'' : ' '), ta);
	refresh();
	n = 0;
	while((ch = getch()) != '\n'){
		if (ch != EOF){
			buf[n++] = ch;
			addch(ch);
			refresh();
		}
		if(ch == '' && n > 1)
			n -= 2;
	}
	buf[n] = '\0';
	buf[9] = '\0';
	dir = pos[player].dir;
	vma = ma;
	for (n = 0; buf[n]; n++)
		if (!(buf[n] == 'r' || buf[n] == '\n' || buf[n] == 'l' || (buf[n] == '0' && !n) || isdigit(buf[n]) || buf[n] == 'b' || (buf[n] == 'd' && !n))){
			if (isspace(buf[n])){
				strcpy(buf+n, buf+n+1);
				n--;
			} else {
				Signal("Syntax error.",0,0);
				buf[n--] = '\0';
			}
		}
		else
			switch(buf[n]){
				case 'l':
					dir -= 2;
				case 'r':
					dir++;
					if (!dir) dir = 8;
					if (dir == 9) dir = 1;
					if (last == 't'){
						Signal("Error; ship can't turn that fast.", 0, 0);
						buf[n--] = '\0';
					}
					last = 't';
					ma--;
					ta--;
					vma = min(ma, maxmove(player, dir, 0));
					if (ta < 0 && moved || vma < 0 && moved)
						buf[n--] = '\0';
					break;

				case 'b':
					ma--;
					vma--;
					last = 'b';
					if (ta < 0 && moved || vma < 0 && moved)
						buf[n--] = '\0';
					break;

				case '0':
				case 'd':
					buf[n--] = '\0';
					break;

				case '\n':
					buf[n] = '\0';
					break;

				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
					if (last == '0'){
						Signal("Error; value out of range.", 0, 0);
						buf[n--] = '\0';
					}
					last = '0';
					moved = 1;
					ma -= buf[n] - '0';
					vma -= buf[n] - '0';
					if (ta < 0 && moved || vma < 0 && moved)
						buf[n--] = '\0';
					break;

			} /* end switch and else and for */
	if (ta < 0 && moved || vma < 0 && moved || af && turnfirst(buf) && moved){
		Signal("Movement error.", 0, 0);
		if (ta < 0 && moved){
			if (scene[game].ship[player].file -> FS == 1){
				Write(FILES + player, 0, 230, 0);
				Signal("No hands to set full sails.", 0, 0);
			}
		}
		else if (ma >= 0)
			buf[1] = '\0';
	}
	if (af && !moved){
		if (scene[game].ship[player].file -> FS == 1){
			Write(FILES + player, 0, 230, 0);
			Signal("No hands to set full sails.", 0, 0);
		}
	}
	strcpy(movebuf, buf);
	if (!*movebuf) strcpy(movebuf, "d");
	Write(FILES + player, 1, 72, movebuf);
	Signal("Helm: %s.", -1, movebuf);
}

boarding()
{
	register int n;
	int crew[3];
	int captured, men = 0;
	struct shipspecs *ptr;

	ptr = &specs[scene[game].ship[player].shipnum];
	crew[0] = ptr -> crew1;
	crew[1] = ptr -> crew2;
	crew[2] = ptr -> crew3;
	for(n=0; n < 3; n++){
		if (scene[game].ship[player].file -> OBP[n].turnsent)
			    men += scene[game].ship[player].file -> OBP[n].turnsent;
	}
	for(n=0; n < 3; n++){
		if (scene[game].ship[player].file -> DBP[n].turnsent)
			    men += scene[game].ship[player].file -> DBP[n].turnsent;
	}
	if (men){
		crew[0] = men/100 ? 0 : crew[0] != 0;
		crew[1] = (men%100)/10 ? 0 : crew[1] != 0;
		crew[2] = men%10 ? 0 : crew[2] != 0;
	} else {
		crew[0] = crew[0] != 0;
		crew[1] = crew[1] != 0;
		crew[2] = crew[2] != 0;
	}
	for (n=0; n < scene[game].vessels; n++){
		if ((captured = scene[game].ship[n].file -> captured) < 0)
			captured = n;
		if (n != player && pos[n].dir && range(player, n) <= 1 && scene[game].ship[player].nationality != scene[game].ship[captured].nationality){
			if (meleeing(player, n) && crew[2]){
				Signal("How many more to board the %s (%c%c)? ",n,0);
				parties(crew, n, 200);
			}
			else if ((foul(player, n) || grapple(player, n)) && crew[2]){
				Signal("Crew sections to board the %s (%c%c) (3 max) ?", n, 0);
				parties(crew, n, 200);
			}
		}
	}
	if (crew[2]){
		Signal("How many sections to repel boarders? ", 0, 0);
		parties(crew, player, 260);
	}
}

parties(crew, n, offset)
int crew[3], n, offset;
{
	register int k, j, men; 
	struct BP * ptr;
	int  buf;
	int temp[3];

	for (k=0; k < 3; k++)
		temp[k] = crew[k];
	while((buf = getch()) == EOF);
	addch(buf);
	if (isdigit(buf)){
		ptr = offset == 200 ? scene[game].ship[player].file -> OBP : scene[game].ship[player].file -> DBP ; 
		for (j = 0; j < 3 && ptr[j].turnsent; j++);
		if (!ptr[j].turnsent && buf > '0'){
			men = 0;
			for (k=0; k < 3 && buf > '0'; k++){
				men += crew[k]*power(10, 2-k);
				crew[k] = 0;
				if (men) buf -= 1;
			}
			if (buf > '0')
				Signal("Sending all crew sections.", 0, 0);
			Write(FILES + player, 0, 30 + (offset > 200)*18 + 6*j, turn);
			Write(FILES + player, 0, 30 + (offset > 200)*18 + 6*j + 2, n);
			Write(FILES + player, 0, 30 + (offset > 200)*18 + 6*j + 4, men);
			switch(offset){
				case 200:
					wmove(slot, 0, 0);
					for (k=0; k < 3; k++)
						if (temp[k] && !crew[k])
							waddch(slot, k + '1');
						else
							wmove(slot, 0, 1 + k);
					wmove(slot, 1, 0);
					waddstr(slot, "OBP");
					makesignal("boarding the %s (%c%c)", n, player);
					break;
				case 260:
					wmove(slot, 2, 0);
					for (k=0; k < 3; k++)
						if (temp[k] && !crew[k])
							waddch(slot, k + '1');
						else
							wmove(slot, 2, 1 + k);
					wmove(slot, 3, 0);
					waddstr(slot, "DBP");
					makesignal("repelling boarders", 0, player);
					break;
			}
			wrefresh(slot);
		}
		else
			Signal("Sending no crew sections.", 0, 0);
	}
}

power(base, exp)
int base, exp;
{
	switch(exp){
		case 0:
			return(1);
		case 1:
			return(base);
		case 2:
			return(base * base);
	}
	return(0);
}

repair()
{
	int buf;
	int *repairs;
	struct shipspecs *ptr;

	if (!repaired && !loaded && !fired && !changed && !turned()){
		ptr = &specs[scene[game].ship[player].shipnum];
		Signal("Repair (hull, guns, rigging)? ", 0, 0);
		while((buf = getch()) == EOF);
		addch(buf);
		switch(buf){
			case 'h':
				repairs = &scene[game].ship[player].file -> RH;
				break;
			case 'g':
				repairs = &scene[game].ship[player].file -> RG;
				break;
			case 'r':
				repairs = &scene[game].ship[player].file -> RR;
				break;
			default:
				Signal("Avast heaving!", 0, 0);
				return;
		}
		repaired = 1;
		*repairs += 1;
		if (*repairs >= 3){
			*repairs = 0;
		}
		if (!*repairs){
			switch(buf){
				case 'h':
					if (ptr -> hull < ptr -> guns/4)
						Write(SPECS + player, 0, 10, ptr -> hull + 2);
					else buf = 0;
					break;
				case 'g':
					if (ptr -> gunL < ptr -> gunR){
						if (ptr -> gunL + ptr -> carL < ptr -> guns/5)
							Write(SPECS + player, 0, 20, ptr -> gunL + 2);
						else buf = 0;
					} else
						if (ptr -> gunR + ptr -> carR < ptr -> guns/5)
							Write(SPECS + player, 0, 22, ptr -> gunR + 2);
						else buf = 0;
					break;
				case 'r':
					if (!ptr -> rig4)
						Write(SPECS + player, 0, 34, ptr -> rig4 + 2);
					else if (!ptr -> rig3)
						Write(SPECS + player, 0, 32, 2);
					else if (!ptr -> rig2)
						Write(SPECS + player, 0, 30, 2);
					else if (ptr -> rig1 < 4)
						Write(SPECS + player, 0, 28, 2);
					else buf = 0;
					break;
			}
			if (!buf)
				Signal("Repairs completed.", 0, 0);
		}
	}
	else
		Signal("No hands free to repair",0,0);
}

turned()
{
	register int n;

	for (n=0; movebuf[n]; n++)
		if (movebuf[n] == 'r' || movebuf[n] == 'l')
			return(1);
	return(0);
}

loadplayer()
{
	int buf;
	int loadL, loadR, ready, load, *Ready, *Load;

	if (!specs[scene[game].ship[player].shipnum].crew3){
		Signal("out of crew",0,0);
		return(0);
	}
	Load = &scene[game].ship[player].file -> loadL;
	Ready = &scene[game].ship[player].file -> readyL;
	loadL = *Load;
	loadR = *(Load + 1);
	if (!loadL && !loadR){
		Signal("Load which broadside (left or right)? ", 0, 0);
		while((buf = getch()) == EOF);
		addch(buf);
		if (buf == 'r')
			loadL = 1;
		else
			loadR = 1;
	}
	if ((!loadL && loadR || loadL && !loadR)){
		Signal("Reload with (round, double, chain, grape)? ", 0, 0);
		while((buf = getch()) == EOF);
		addch(buf);
		switch(buf){
			case 'r':
				load = ROUND;
				ready = 1;
				break;
			case 'd':
				load = DOUBLE;
				ready = 2;
				break;
			case 'c':
				load = CHAIN;
				ready = 1;
				break;
			case 'g':
				load = GRAPE;
				ready = 1;
				break;
			default:
				Signal("Broadside not loaded.", 0, 0);
				return;
		}
		if (!loadR){
			*(Load + 1) = load;
			*(Ready + 1) = ready;
		}
		else {
			*Load = load;
			*Ready = ready;
		}
		loaded = 1;
	}
}

changesail()
{
	int buf;
	int rig, full;

	rig = specs[scene[game].ship[player].shipnum].rig1;
	full = scene[game].ship[player].file -> FS;
	if ((windspeed == 6) || (windspeed == 5 && specs[scene[game].ship[player].shipnum].class > 4))
		rig = 0;
	if (specs[scene[game].ship[player].shipnum].crew3 && rig){
		if (!full){
			Signal("Increase to Full sails? ", 0, 0);
			while((buf = getch()) == EOF);
			addch(buf);
			if (buf == 'y'){
				changed = 1;
				Write(FILES + player, 0, 230, 1);
			}
		}
		else {
			Signal("Reduce to Battle sails? ", 0, 0);
			while((buf = getch()) == EOF);
			addch(buf);
			if (buf == 'y'){
				Write(FILES + player, 0, 230, 0);
				changed = 1;
			}
		}
	}
	else if (!rig)
		Signal("Sails rent to pieces",0,0);
}


signalflags()
{
	register int n;

	for(n=0; n < scene[game].vessels; n++){
		if (*scene[game].ship[n].file -> signal){
			putchar('\7');
			Signal("%s (%c%c): %s",n,scene[game].ship[n].file -> signal);
			*scene[game].ship[n].file -> signal = '\0';
		}
	}
}

iplotships()		/* new turn; also plot-ships */
{
	repaired = loaded = fired = changed = 0;
	plotships();
}


plotships()			/* uses ken's package */
{
	register int n;
	char ch;
	int sternr,sternc;

	getyx(stdscr, ylast, xlast);
	screen();
	readpos();
	werase(view);
	if (pos[player].row < viewrow + 5)
		viewrow = pos[player].row - ROWSINVIEW + 5;
	else if (pos[player].row > viewrow + ROWSINVIEW - 5)
		viewrow = pos[player].row - 5;
	if (pos[player].col < viewcol + 10)
		viewcol = pos[player].col - COLSINVIEW + 10;
	else if (pos[player].col > viewcol + COLSINVIEW - 10)
		viewcol = pos[player].col - 10;
	for (n=0; n < scene[game].vessels; n++)
		if (pos[n].dir && pos[n].row > viewrow && pos[n].row < viewrow + ROWSINVIEW && pos[n].col > viewcol && pos[n].col < viewcol + COLSINVIEW){
			wmove(view, pos[n].row - viewrow, pos[n].col - viewcol);
			waddch(view, colours(n));
			ch = sterncolor(n, &sternr, &sternc);
			wmove(view, sternr - viewrow, sternc - viewcol);
			waddch(view, ch);
		}
	wrefresh(view);
	move(ylast, xlast);
	refresh();
}

acceptsignal()
{
	int ch;
	char buf[60];
	register int n;

	if(scroll == 23) scroll = 18;
	Signal("Message? ",0,0);
	buf[0] = 34;
	n = 1;
	while((ch = getch()) != '\n'){
		if (ch != EOF){
			buf[n++] = ch;
			addch(ch);
			refresh();
		}
		if (ch == '' && n > 1)
			n -= 2;
	}
	buf[n] = 34;
	buf[n+1] = '\0';
	buf[59] = '\0';
	Write(FILES + player, 1, 164, buf);
}


board()
{
	register int n;
	char *name;
	int class, junk;

	clear();
	werase(view);
	werase(slot);
	move(1,0);
	for (n=0; n < 80; n++)
		addch('-');
	move(17,0);
	for (n=0; n < 80; n++)
		addch('-');
	for (n=2; n < 17; n++){
		mvaddch(n, 0,'|');
		mvaddch(n, 79, '|');
	}
	mvaddch(1,0,'+');
	mvaddch(17,0,'+');
	mvaddch(1,79,'+');
	mvaddch(17,79,'+');
	wmove(view, 2, 27);
	waddstr(view, "Wooden Ships & Iron Men");
	wmove(view, 4, (77 - lengthof(scene[game].name))/2);
	waddstr(view, scene[game].name);
	refresh();
	wrefresh(view);
	switch((class = specs[scene[game].ship[player].shipnum].class)){
		case 2:
		case 1:
			name = "SOL";
			break;
		case 3:
		case 4:
			name = "Frigate";
			break;
		case 5:
		case 6:
			name = "Sloop";
			break;
	}
	move(0,0);
	printw("Class %d %s (%d guns) '%s' (%c%c)", class, name, specs[scene[game].ship[player].shipnum].guns, scene[game].ship[player].shipname, colours(player), sterncolor(player, &junk, &junk));
}

clearline()
{
	register int n;

	move(scroll-1, 0);
	for (n=0; n < 59; n++)
		addch(' ');
	move(scroll-1, 0);
}



Signal(fmt, shipnum, string)
int shipnum;
char *fmt, *string;
{
	int junk;

	move(scroll++, 0);
	clearline();
	if (scroll > 23) scroll = 18;
	if (shipnum == -1)
		printw(fmt, string);
	else if (*string == '*')
		printw(fmt, "computer", '0','0', string);
	else
		printw(fmt, scene[game].ship[shipnum].shipname, colours(shipnum), sterncolor(shipnum, &junk, &junk), string);
	refresh();
}

char *quality(shipnum)
int shipnum;
{
	switch(specs[scene[game].ship[shipnum].shipnum].qual){

		case 5:
			return("elite");
		case 4:
			return("crack");
		case 3:
			return("mundane");
		case 2:
			return("green");
		case 1:
			return("mutinous");
	}
}

char *info(ship, final)
int ship;
char *final;
{
	sprintf(final, "%d gun \0", specs[scene[game].ship[ship].shipnum].guns);
	switch(specs[scene[game].ship[ship].shipnum].class){
		case 1:
		case 2:
			strcat(final, "Ship of the Line");
			break;
		case 3:
			strcat(final, "Frigate");
			break;
		case 4:
			strcat(final, "Corvette");
			break;
		case 5:
			strcat(final, "Sloop");
			break;
		case 6:
			strcat(final, "Brig");
			break;
	}
	return(final);
}

screen()
{
	int class;
	register int n;
	int dr = 0, dc = 0;
	struct shipspecs *data;
	struct File *ptr;

	scene[game].ship[player].file -> readyL--;
	scene[game].ship[player].file -> readyR--;
	movebuf[0] = '\0';
	sync();
	if (turn % 50 == 0)
		Write(SCENARIO, 0, 10, 1);	/* still playing */
	windspeed = scene[game].windspeed;
	winddir = scene[game].winddir;
	turn = scene[game].turn;
	move(0, 47);
	ptr = scene[game].ship[player].file;
	data = &specs[scene[game].ship[player].shipnum];
	if (ptr -> FS == 1)
		Write(FILES + player, 0, 230, 2);
	printw("Points:%3d Fouls:%2d  Grapples:%2d",ptr -> points, fouled(player), grappled(player));
	move(17, 36);
	printw("Turn %d", turn);
	move(18, 59);
	printw("Load  %c%c %c%c", symbol(ptr -> loadL), iinitial(ptr -> readyL), symbol(ptr -> loadR), iinitial(ptr -> readyR));
	move(19, 59);
	printw("Hull %2d", data -> hull);
	move(20, 59);
	printw("Crew %2d %2d %2d", data -> crew1, data -> crew2, data -> crew3);
	move(21, 59);
	printw("Guns %2d %2d", data -> gunL, data -> gunR);
	move(22, 59);
	printw("Carr %2d %2d", data -> carR, data -> carL);
	move(23, 59);
	printw("Rigg %d %d %d ", data -> rig1, data -> rig2, data -> rig3);
	if (data -> rig4 < 0)
		addch('-');
	else
		printw("%d", data -> rig4);
	move(18, 74);
	printw("0 %d(%d)", maxmove(player, winddir + 3, -1), maxmove(player, winddir + 3, 1));
	move(19, 73);
	addstr("\\|/");
	move(20, 73);
	printw("-^-%d(%d)", maxmove(player, winddir + 2, -1), maxmove(player, winddir + 2, 1));
	move(21, 73);
	addstr("/|\\");
	move(22, 74);
	printw("| %d(%d)", maxmove(player, winddir + 1, -1), maxmove(player, winddir + 1, 1));
	move(23, 73);
	printw("%d(%d)", maxmove(player, winddir, -1), maxmove(player, winddir, 1));
	refresh();
	if (!boarders(player, 0)){
		wmove(slot, 0, 0);
		waddstr(slot, "   ");
		wmove(slot, 1, 0);
		waddstr(slot, "   ");
	} else {
		wmove(slot, 1, 0);
		waddstr(slot, "OBP");
	}
	if (!boarders(player, 1)){
		wmove(slot, 2, 0);
		waddstr(slot, "   ");
		wmove(slot, 3, 0);
		waddstr(slot, "   ");
	} else {
		wmove(slot, 3, 0);
		waddstr(slot, "DBP");
	}
	wmove(slot, 12, 0);
	if (n = scene[game].ship[player].file -> RH)
		wprintw(slot, "%dRH", n);
	else
		waddstr(slot, "   ");
	wmove(slot, 13, 0);
	if (n = scene[game].ship[player].file -> RG)
		wprintw(slot, "%dRG", n);
	else
		waddstr(slot, "   ");
	wmove(slot, 14, 0);
	if (n = scene[game].ship[player].file -> RR)
		wprintw(slot, "%dRR", n);
	else
		waddstr(slot, "   ");
	wmove(slot, 7, 1);
	wprintw(slot,"%d", windspeed);
	drdc(&dr, &dc, winddir);
	wmove(slot, 7, 0); waddch(slot, ' ');
	wmove(slot, 7, 2); waddch(slot, ' ');
	wmove(slot, 6, 0); waddch(slot, ' ');
	wmove(slot, 6, 1); waddch(slot, ' ');
	wmove(slot, 6, 2); waddch(slot, ' ');
	wmove(slot, 8, 0); waddch(slot, ' ');
	wmove(slot, 8, 1); waddch(slot, ' ');
	wmove(slot, 8, 2); waddch(slot, ' ');
	wmove(slot, (7 - dr), (1 - dc));
	switch(winddir){
		case 1:
		case 5:
			waddch(slot, '|');
			break;
		case 2:
		case 6:
			waddch(slot, '/');
			break;
		case 3:
		case 7:
			waddch(slot, '-');
			break;
		case 4:
		case 8:
			waddch(slot, '\\');
			break;
	}
	wmove(slot, (7 + dr), (1 + dc));
	waddch(slot, '+');
	wrefresh(slot);
	signal(SIGALRM, iplotships);	/* new turn and plot-ships */
	alarm(7);
}

extern char iinitial(ready)
int ready;
{
	if (ready <= -30000)
		return('!');
	if (ready > 0)
		return('*');
	return(' ');
}

char symbol(number)
int number;
{
	switch(number){
		case GRAPE:
			return('G');
		case ROUND:
			return('R');
		case DOUBLE:
			return('D');
		case CHAIN:
			return('C');
	}
	return('-');
}

