|
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; } }