DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T i

⟦e71ebe9ca⟧ TextFile

    Length: 12493 (0x30cd)
    Types: TextFile
    Names: »input.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/General/Kriegspiel/input.c« 

TextFile

/* input.c */

#include "externs.h"
#include <ctype.h>
#include <strings.h>
#include <sys/time.h>

char instr [MAXBUFF];
static char input_buff [MAXBUFF], *input_p = (char *) NULL;

entermove (pstart, pend, color, pawntries)
	int *pstart, *pend, color, pawntries;
{
	int i, j, readfds;
	int counter = 0;
	struct timeval timeout;
	char c;

	timeout.tv_sec = (long int) 1;
	timeout.tv_usec = (long int) 0;
	wclear (win [OPPONENT]);
	while (TRUE) {
		drawok [color] = FALSE;
		if (color == ourcolor) {
			printf ("\007");    /* ring bell */
			if (drawok [1 - color]) {
				wclear (win [MESSAGE]);
				waddstr (win [MESSAGE],
					 "draw offered\ntype yes or no\n");
			}
			wclear (win [INPUT]);
			waddstr (win [INPUT], ": ");
			waddstr (win [PROMPT], "your move");
			i = 0;
			while (TRUE) {
				move (win [INPUT]->_cury + win [INPUT]->_begy,
				      win [INPUT]->_curx + win [INPUT]->_begx);
				refresh ();
				instr [i] = getchar ();
				if (instr [i] == '\n'
				||  instr [i] == '\r')
					break;
				else if (instr [i] == '\f') {	/* ^L */
					redraw();
					continue;
				} else if (instr [i] == '\b'	/* ^H */
				|| instr [i] == '\177') {	/* delete */
					if (i > 0) {
						--i;
						wmove( win [INPUT],
						       win [INPUT]->_cury,
						       win [INPUT]->_curx - 1);
						wdelch (win [INPUT]);
					}
					continue;
				} else if (instr [i] == '\030'	/* ^X */
				|| instr [i] == '\025') {	/* ^U */
					wclear (win [INPUT]);
					waddstr (win [INPUT], ": ");
					i = 0;
					continue;
				} else if (isupper (instr [i]))
					tolower (instr [i]);
				wclear (win [LEGAL]);
				if (isprint (instr [i]))
					waddch (win [INPUT], instr [i++]);
			}
			instr [i] = '\000';
			wclear (win [INPUT]);
			if (send (sock, instr, strlen (instr) + 1, 0) < 0)
				error ("send in entermove");
		} else {
			i = 0;
			wclear (win [MESSAGE]);
			waddstr (win [MESSAGE],
				 "waiting for\nopponent's\nmove");
			refresh ();
			while (!(input_p && *input_p)) {
				readfds = 1 + (1 << sock);
				while (select (sock + 1, &readfds, (int *)
					       NULL, (int *) NULL,
					       &timeout) < 0)
					if (errno != EINTR)
						error ("select in entermove");
				if (! (readfds & (1 << sock))) {
					wclear (win [CLOCK]);
					if (counter++ % 2 == 1)
						waddch (win [CLOCK],'/');
					else
						waddch (win [CLOCK],'\\');
					move (win [CLOCK]->_begy,
					      win [CLOCK]->_begx);
					refresh();
					if (readfds & 1) {
						c = getch();
						if (c == '\f'	/* ^L */)
							redraw();
					}
				}
				else
					break;
				wclear (win [LEGAL]);
			}
			wclear (win [LEGAL]);
			if (!(input_p && *input_p)) {
				for (i = 0; i < MAXBUFF; i++)
					input_buff [i] = '\0';
				while (recv (sock, input_buff, MAXBUFF, 0) < 0)
					if (errno != EINTR)
						error ("recv in entermove");
				input_p = input_buff;
			}
			strcpy (instr, input_p);
			input_p = index (input_p, '\0');
			input_p++;
		}
		for (i = 0; i < strlen (instr); i++)
			if (isupper (instr [i]))
				instr [i] = tolower (instr [i]);
		wclear (win [PROMPT]);
		if (!strcmp (instr, "draw")) {
			drawok [color] = TRUE;
			break;
		} else if (!strcmp (instr, "resign")) {
			resign = TRUE;
			break;
		} else if (!strcmp (instr, "very dead\3")) {
			dead = TRUE;
			break;
		} else if (drawok [1 - color]) {
			if (!strcmp (instr, "yes")) {
				drawok [color] = TRUE;
				break;
			} else if (!strcmp (instr, "no")) {
				if (ourcolor != color)
					waddstr (win[MESSAGE], "draw refused");
				break;
			}
		} else if (!strcmp (instr, "o-o-o")
		&& kingloc [color] % 10 == 5) {
			*pstart = kingloc [color];
			*pend = kingloc [color] - 2;
			break;
		} else if (!strcmp (instr, "o-o")
		&& kingloc [color] % 10 == 5) {
			*pstart = kingloc [color];
			*pend = kingloc [color] + 2;
			break;
		} else if (!strncmp (instr, "help", 4) && color == ourcolor)
			help (FALSE);
		else if (!strncmp (instr, "long", 4) && color == ourcolor)
			help (TRUE);
		else if (!strncmp (instr, "say", 3)) {
			if (color != ourcolor) {
				wclear (win [OPPONENT]);
				waddstr (win [OPPONENT], "message:\n");
				waddstr (win [OPPONENT], instr + 3);
				waddch (win [OPPONENT], '\n');
			}
		} else if ((!option [ANNOUNCEPAWNS])
		&& (!strcmp (instr, "any")))
			if (pawntries)
				waddstr (win [PAWNTRIES], "pawntries\r");
			else
				waddstr (win [PAWNTRIES], "no pawntries\r");
		else {
			if ((i = parse_algebraic_move(pstart,pend,color))
			    != TRUE)
				j = parse_descriptive_move (pstart,pend,color);
			if (i == TRUE || j == TRUE)
				break;
			else
				illegal (((i < j) ? i : j), color);
		}
	}
}

#define boardpos(col, row)  ((9 - (row)) * 10 + (col))
#define RIGHT_SIDE 2
#define RIGHT_FILE 1

/* parse an algebraic move (e2-e4), and return TRUE for non error */
parse_algebraic_move (pstart, pend, color)
	int *pstart, *pend, color;
{
	int foundpiece = FALSE, i, j, piece, spot;
	LIST piecemoves (), lmember ();

	if (strlen (instr) == 5)
		if (instr [0] >= 'a' && instr [0] <= 'h'
		&&  instr [1] >= '1' && instr [1] <= '8'
		&&  instr [3] >= 'a' && instr [3] <= 'h'
		&&  instr [4] >= '1' && instr [4] <= '8') {
			*pstart = boardpos (instr[0]-'a'+1, instr[1]-'0');
			*pend   = boardpos (instr[3]-'a'+1, instr[4]-'0');
			if (option [REVERSE] && color == BLACK) {
				*pstart = 99 - *pstart;
				*pend   = 99 - *pend;
			}
			return TRUE;
		} else

			return ILLEGAL_FORMAT;
	else if (strlen (instr) == 4)
		if (instr [0] >= 'a' && instr [0] <= 'h'
		&&  instr [1] >= '1' && instr [1] <= '8'
		&&  instr [2] >= 'a' && instr [2] <= 'h'
		&&  instr [3] >= '1' && instr [3] <= '8') {
			*pstart = boardpos (instr[0]-'a'+1, instr[1]-'0');
			*pend   = boardpos (instr[2]-'a'+1, instr[3]-'0');
			if (option [REVERSE] && color == BLACK) {
				*pstart = 99 - *pstart;
				*pend   = 99 - *pend;
			}
			return TRUE;
		} else

			return ILLEGAL_FORMAT;
	else if (strlen (instr) == 2) {
		if (instr [0] < 'a' || instr [0] > 'h')
			return ILLEGAL_FORMAT;
		else if (instr [1] >= 'a' && instr [1] <= 'h') {
			/* pawn take */
			for (i = 2; i <= 7 ; i++) {
				spot = boardpos (instr[0]-'a'+1, i);
				if (option [REVERSE] && color == BLACK)
					spot = 99 - spot;
				if (whose [spot] == color 
				&& occupant [spot] == PAWN)
					if (foundpiece)
						return AMBIGUOUS_FROM;
					else
						foundpiece = spot;
			}
			if (foundpiece) {
				*pstart = foundpiece;
				if (option [REVERSE] && color == BLACK)
					*pend = boardpos ('i'-instr[1],
							  9 - foundpiece / 10)
						+ pawndir [color];
				else
					*pend = boardpos (instr[1]-'a'+1,
							  9 - foundpiece / 10)
						+ pawndir [color];
				return TRUE;
			} else
				return NO_FROM;
		} else if (instr [1] >= '1' && instr [1] <= '8') {
			/* pawn move */
			*pend = boardpos (instr[0]-'a'+1, instr[1]-'0');
			if (option [REVERSE] && color == BLACK)
				*pend = 99 - *pend;
			if (((color == BLACK) && (*pend <= 28))
			||  ((color == WHITE) && (*pend >= 71)))
			    return BADPAWNPUSH;
			if ((whose [*pstart= *pend - pawndir [color]] == color
			     && occupant [*pstart] == PAWN)
			|| (whose [*pstart= *pstart - pawndir [color]] == color
			    && occupant [*pstart] == PAWN))
				return TRUE;
			else
				return BADPAWNPUSH;
		} else
			return ILLEGAL_FORMAT;
	} else if (strlen (instr) == 3) {    /* eg. nc6 */
		if ((piece = piecetype(instr [0])) == ILLEGAL_PIECE)
			return ILLEGAL_PIECE;
		if (instr [1] < 'a' || instr [1] > 'h'
		|| instr [2] < '0' || instr [2] >'h')
			return ILLEGAL_FORMAT;
		*pend = boardpos (instr [1] - 'a' + 1, instr [2] - '0');
		if (option [REVERSE] && color == BLACK)
			*pend = 99 - *pend;
		for (i = 1; i <= 8; i++) {
			for (j = 1; j <= 8; j++) {
				*pstart = boardpos (i, j);
				if (whose [*pstart] != color
				|| occupant [*pstart] != piece
				|| !lmember (*pend, piecemoves(*pstart,TRUE)))
					continue;
				if (foundpiece)
					return AMBIGUOUS_FROM;
				foundpiece = *pstart;
			}
		}
		if (*pstart = foundpiece)
			return TRUE;
		else
			return NO_FROM;
	}
	return ILLEGAL_FORMAT;   /* shoud never be reached */
}

/* parse a descriptive move (n-kb3), return TRUE for non error */
parse_descriptive_move (pstart, pend, color)
	int *pstart, *pend, color;
{
	char *sfrom, *sto, *alloca(), *index(), *afterslash;
	int nlegalbyfile = 0, nlegalbyside = 0, fromlegal = 0, frombyfile
		, frombyside, pawntake = FALSE, piece;
	LIST tryto, targets, piecemoves ();
	int i, j, spot, tobyfile, tobyside;
	struct {
		int row;
		int col;
		int goodness;
	} xfrom[100];
  
	/* sfrom is from string, sto is to string */
	sfrom = alloca (strlen (instr) + 1);
	strcpy(sfrom, instr);
	if ((sto = index (sfrom, '-')) == NULL)
		if ((sto = index (sfrom, 'x')) != NULL)
			pawntake = TRUE;
		else
			return ILLEGAL_FORMAT;
	*sto++ = '\0';
	if ((afterslash = index (sfrom, '/')) != NULL)
		*afterslash++ = '\0';
	if ((piece = piecetype(sfrom [strlen (sfrom) - 1])) == ILLEGAL_PIECE)
		return ILLEGAL_PIECE;
	pawntake = pawntake && piece == PAWN;
	sfrom [strlen (sfrom) - 1] = '\0';

	/* build a list of legal from moves */
	for (i = 1; i <= 8; i++) {
		for (j = 1; j <= 8; j++) {
			spot = (9 - i) * 10 + j;
			if (whose [spot] != color)
				continue;
			if (occupant [spot] != piece)
				continue;
			xfrom [fromlegal].goodness = RIGHT_FILE;
			if (afterslash) {
				switch (xfrom [fromlegal].goodness
					= matchpos(afterslash, spot, color)) {
				case FALSE:
					continue;
				case ILLEGAL_FORMAT:
					return ILLEGAL_FORMAT;
				case RIGHT_SIDE:
				case RIGHT_FILE:
					break;
				}
			}
			if (*sfrom) {
				switch (xfrom [fromlegal].goodness
					= matchpos(sfrom, spot, color)) {
				case FALSE:
					continue;
				case ILLEGAL_FORMAT:
					return ILLEGAL_FORMAT;
				case RIGHT_SIDE:
				case RIGHT_FILE:
					break;
				}
			}
			xfrom[fromlegal].row = i;
			xfrom[fromlegal].col = j;
			fromlegal++;
		}
	}

	/* find all the consistent 'to' moves for those 'from' moves */
	for (i = 0; i < fromlegal; i++) {
		spot = (9 - xfrom [i].row) * 10 + xfrom [i].col;
		targets = piecemoves (spot, TRUE);
		for (tryto = targets; tryto != NULL; tryto = tryto->n) {
			switch (matchpos(sto, tryto->i, color)) {
			case RIGHT_FILE:
				if (piece == PAWN
				&& pawntake
				    == ((tryto->i % 10) == (xfrom[i].col)))
					continue;
				if (xfrom [i].goodness == RIGHT_FILE) {
					frombyfile = i;
					tobyfile = tryto -> i;
					nlegalbyfile++;
				}
				frombyside = i;
				tobyside = tryto -> i;
				nlegalbyside++;
				break;
			case FALSE:
			case RIGHT_SIDE:
				continue;
			case ILLEGAL_FORMAT:
				return ILLEGAL_FORMAT;
			}
		}
	}

	/* complain if there are too many or if there are none */
	if (nlegalbyside != 1 && nlegalbyfile != 1) {
		if (nlegalbyside > 1)
			return AMBIGUOUS;
		else
			return NO_MOVE;
	}

	if (nlegalbyside == 1) {
		/* frombyside and tobyside now define the unique legal move */
		*pstart = (9 - xfrom[frombyside].row) * 10
			+ xfrom[frombyside].col;
		*pend = tobyside;
	} else if (nlegalbyfile == 1) {
		/* frombyfile and tobyfile now define the unique legal move */
		*pstart = (9 - xfrom[frombyfile].row) * 10
			+ xfrom[frombyfile].col;
		*pend = tobyfile;
	}
	return TRUE;
}

/* matchpos -- tells whether a square number matches the description
   desc is of the form b4 or qb4 or just b or 4 */
static
matchpos(desc, squareno, color)
	char *desc;
	int squareno, color;
{
	static char *piececol = "rnbqkbnr";
	char side = FALSE, piece = FALSE, rownum;
	int row, col;

	/* get row and col with player's king on (4,1)	*/
	/* (black's board is reflected)			*/
	row = 9 - squareno / 10;
	col = squareno % 10;
	if (color == BLACK)
		row = 9 - row;

	if (desc [0] == 'k' || desc [0] == 'q')
		side = desc++ [0];
	if (isalpha (desc [0]))
		piece = desc++ [0];
	if (rownum = isdigit (desc [0]))
		rownum = desc++ [0];
	if (( piece && index(piececol, piece) == NULL)
	|| ( rownum && index("12345678", rownum) == NULL)
	|| desc [0] != '\0')
		return ILLEGAL_FORMAT;
	else if ((side == 'k' && col <= 4) || (side == 'q' && col >= 5)
	|| (rownum && row != rownum - '0')
	|| (piece && piececol [col - 1] != piece))
		return FALSE;
	else if (side && !piece && piececol [col - 1] != side)
		return RIGHT_SIDE;   /* eg. b/q-n2 when b is on queen side */
	else
		return RIGHT_FILE;   /* eg. b/q-n2 when b is in queen file */
}

static piecetype(letter)
	char letter;
{
	switch (letter) {
	case 'p':
		return PAWN;
	case 'r':
		return ROOK;
	case 'n':
		return KNIGHT;
	case 'b':
		return BISHOP;
	case 'q':
		return QUEEN;
	case 'k':
		return KING;
	default:
		return ILLEGAL_PIECE;
	}
}