|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T i
Length: 12493 (0x30cd)
Types: TextFile
Names: »input.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Kriegspiel/input.c«
/* 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;
}
}