static void cfollow(B *b, VT *vt, off_t byte) { W *w; int xn; if (vt && piscol(vt->vtcur) >= vt->width) xn = 1; /* xn glitch: cursor is past end of line */ else xn = 0; if (b->oldcur && b->shell_flag) { b->shell_flag = 0; pgoto(b->oldcur, byte); b->oldcur->xcol = piscol(b->oldcur); if (xn) b->oldcur->xcol = vt->width - 1; } if ((w = maint->topwin) != NULL) { do { if (w->watom->what & TYPETW) { BW *bw = (BW *)w->object; if (bw->shell_flag) { bw->shell_flag = 0; pgoto(bw->cursor, byte); bw->cursor->xcol = piscol(bw->cursor); if (xn) bw->cursor->xcol = vt->width - 1; if (vt && bw->top->line != vt->top->line && (1 + vt->vtcur->line - vt->top->line) <= bw->h) pline(bw->top, vt->top->line); dofollows(); } } w = w->link.next; } while (w != maint->topwin); } }
int uundo(BW *bw) { UNDOREC *upto; UNDO *undo = bw->b->undo; if (!undo) return -1; if (!undo->nrecs) return -1; if (!undo->ptr) { pgoto(bw->cursor, undo->recs.link.prev->where); undo->ptr = &undo->recs; /* If this return is uncommented, then uundo will jump to where the undo is about to occur before actually undoing anything */ /* return 0; */ } if (undo->ptr->link.prev == &undo->recs) return -1; upto = undo->ptr->link.prev->unit; do { undo->ptr = undo->ptr->link.prev; pgoto(bw->cursor, undo->ptr->where); inundo = 1; doundo(bw, undo->ptr); inundo = 0; } while (upto && upto != undo->ptr); return 0; }
static int cpufire(int x, int y) /* fire away at given location */ { bool hit, sunk; ship_t *ss = NULL; hit = board[PLAYER][x][y] ? MARK_HIT : MARK_MISS; hits[COMPUTER][x][y] = (char) hit; (void) mvprintw(PROMPTLINE, 0, "I shoot at %c%d. I %s!", y + 'A', x, hit ? "hit" : "miss"); if ((sunk = (hit && (ss = hitship(x, y)))) != 0) (void) printw(" I've sunk your %s", ss->name); (void) clrtoeol(); pgoto(y, x); #ifdef A_COLOR if (has_colors()) { if (hit) attron(COLOR_PAIR(COLOR_RED)); else attron(COLOR_PAIR(COLOR_GREEN)); } #endif /* A_COLOR */ (void) addch((chtype) (hit ? SHOWHIT : SHOWSPLASH)); #ifdef A_COLOR (void) attrset(0); #endif /* A_COLOR */ return hit ? (sunk ? S_SUNK : S_HIT) : S_MISS; }
/* fire away at given location */ static bool cpufire(int x, int y) { bool hit, sunk; ship_t *ss; ss = NULL; hits[COMPUTER][x][y] = (hit = (board[PLAYER][x][y])) ? MARK_HIT : MARK_MISS; mvprintw(PROMPTLINE, 0, "I shoot at %c%d. I %s!", y + 'A', x, hit ? "hit" : "miss"); ss = hitship(x, y); sunk = hit && ss; if (sunk) printw(" I've sunk your %s", ss->name); clrtoeol(); pgoto(y, x); #ifdef A_COLOR if (has_colors()) { if (hit) attron(COLOR_PAIR(COLOR_RED)); else attron(COLOR_PAIR(COLOR_GREEN)); } #endif /* A_COLOR */ addch((chtype)(hit ? SHOWHIT : SHOWSPLASH)); #ifdef A_COLOR attrset(0); #endif /* A_COLOR */ return(hit ? (sunk ? S_SUNK : S_HIT) : S_MISS); }
/* fire away at given location */ static int cpufire(int x, int y) { int hit; bool sunk; ship_t *ss = NULL; hits[COMPUTER][x][y] = (hit = (board[PLAYER][x][y])) ? MARK_HIT : MARK_MISS; (void) mvprintw(PROMPTLINE, 0, "I shoot at %c%d. I %s!", y + 'A', x, hit ? "hit" : "miss"); if ((sunk = (hit && (ss = hitship(x, y))))) (void) printw(" I've sunk your %s", ss->name); (void)clrtoeol(); pgoto(y, x); if (has_colors()) { if (hit) attron(COLOR_PAIR(COLOR_RED)); else attron(COLOR_PAIR(COLOR_GREEN)); } (void) addch((chtype)(hit ? SHOWHIT : SHOWSPLASH)); attrset(0); return(hit ? (sunk ? S_SUNK : S_HIT) : S_MISS); }
int uredo(BW *bw) { UNDOREC *upto; UNDOREC *ptr; UNDO *undo = bw->b->undo; if (!undo) return -1; if (!undo->ptr) return -1; if (undo->ptr == &undo->recs) return -1; upto = undo->recs.link.prev->unit; do { ptr = undo->recs.link.prev; pgoto(bw->cursor, ptr->where); inredo = 1; doundo(bw, ptr); inredo = 0; frrec(deque_f(UNDOREC, link, ptr)); /* Delete record created by undo command */ undo->ptr = undo->ptr->link.next; } while (upto && upto != ptr); /* We just deleted one undo record */ --undo->nrecs; return 0; }
static void placeship(int b, ship_t * ss, int vis) { int l; for (l = 0; l < ss->length; ++l) { int newx = ss->x + l * xincr[ss->dir]; int newy = ss->y + l * yincr[ss->dir]; board[b][newx][newy] = ss->symbol; if (vis) { pgoto(newy, newx); (void) addch((chtype) ss->symbol); } } ss->hits = 0; }
static void iappend(BW *bw, struct isrch *isrch, char *s, ptrdiff_t len) { /* Append text and search */ /* Append char and search */ IREC *i = alirec(); SRCH *srch; i->what = len; i->disp = bw->cursor->byte; isrch->pattern = vsncpy(sv(isrch->pattern), s, len); if (!qempty(IREC, link, &isrch->irecs)) { pgoto(bw->cursor, isrch->irecs.link.prev->start); if (globalsrch) globalsrch->wrap_flag = isrch->irecs.link.prev->wrap_flag; } i->start = bw->cursor->byte; if (!globalsrch) srch = mksrch(NULL,NULL,opt_icase,isrch->dir,-1,0,0,0,0); else { srch = globalsrch; globalsrch = 0; } srch->addr = bw->cursor->byte; if (!srch->wrap_p || srch->wrap_p->b!=bw->b) { prm(srch->wrap_p); srch->wrap_p = pdup(bw->cursor, "iappend"); srch->wrap_p->owner = &srch->wrap_p; srch->wrap_flag = 0; } i->wrap_flag = srch->wrap_flag; setpat(srch, vsncpy(NULL, 0, isrch->pattern, sLen(isrch->pattern))); srch->backwards = isrch->dir; if (dopfnext(bw, srch, NULL)) { if(joe_beep) ttputc(7); } enqueb(IREC, link, &isrch->irecs, i); }
static ship_t * hitship(int x, int y) /* register a hit on the targeted ship */ { ship_t *sb, *ss; char sym; int oldx, oldy; getyx(stdscr, oldy, oldx); sb = (turn) ? plyship : cpuship; if ((sym = board[OTHER][x][y]) == 0) return ((ship_t *) NULL); for (ss = sb; ss < sb + SHIPTYPES; ++ss) if (ss->symbol == sym) { if (++ss->hits < ss->length) /* still afloat? */ return ((ship_t *) NULL); else { /* sunk! */ int i, j; if (!closepack) for (j = -1; j <= 1; j++) { int bx = ss->x + j * xincr[(ss->dir + 2) % 8]; int by = ss->y + j * yincr[(ss->dir + 2) % 8]; for (i = -1; i <= ss->length; ++i) { int x1, y1; x1 = bx + i * xincr[ss->dir]; y1 = by + i * yincr[ss->dir]; if (ONBOARD(x1, y1)) { hits[turn][x1][y1] = MARK_MISS; if (turn % 2 == PLAYER) { cgoto(y1, x1); #ifdef A_COLOR if (has_colors()) attron(COLOR_PAIR(COLOR_GREEN)); #endif /* A_COLOR */ (void) addch(MARK_MISS); #ifdef A_COLOR (void) attrset(0); #endif /* A_COLOR */ } else { pgoto(y1, x1); (void) addch(SHOWSPLASH); } } } } for (i = 0; i < ss->length; ++i) { int x1 = ss->x + i * xincr[ss->dir]; int y1 = ss->y + i * yincr[ss->dir]; hits[turn][x1][y1] = ss->symbol; if (turn % 2 == PLAYER) { cgoto(y1, x1); (void) addch((chtype) (ss->symbol)); } else { pgoto(y1, x1); #ifdef A_COLOR if (has_colors()) attron(COLOR_PAIR(COLOR_RED)); #endif /* A_COLOR */ (void) addch(SHOWHIT); #ifdef A_COLOR (void) attrset(0); #endif /* A_COLOR */ } } (void) move(oldy, oldx); return (ss); } } (void) move(oldy, oldx); return ((ship_t *) NULL); }
static int getcoord(int atcpu) { int ny, nx, c; if (atcpu) cgoto(cury, curx); else pgoto(cury, curx); (void) refresh(); for (;;) { if (atcpu) { (void) mvprintw(CYBASE + BDEPTH + 1, CXBASE + 11, "(%d, %c)", curx, 'A' + cury); cgoto(cury, curx); } else { (void) mvprintw(PYBASE + BDEPTH + 1, PXBASE + 11, "(%d, %c)", curx, 'A' + cury); pgoto(cury, curx); } switch (c = getch()) { case 'k': case '8': case KEY_UP: ny = cury + BDEPTH - 1; nx = curx; break; case 'j': case '2': case KEY_DOWN: ny = cury + 1; nx = curx; break; case 'h': case '4': case KEY_LEFT: ny = cury; nx = curx + BWIDTH - 1; break; case 'l': case '6': case KEY_RIGHT: ny = cury; nx = curx + 1; break; case 'y': case '7': case KEY_A1: ny = cury + BDEPTH - 1; nx = curx + BWIDTH - 1; break; case 'b': case '1': case KEY_C1: ny = cury + 1; nx = curx + BWIDTH - 1; break; case 'u': case '9': case KEY_A3: ny = cury + BDEPTH - 1; nx = curx + 1; break; case 'n': case '3': case KEY_C3: ny = cury + 1; nx = curx + 1; break; case FF: nx = curx; ny = cury; (void) clearok(stdscr, TRUE); (void) refresh(); break; #ifdef NCURSES_MOUSE_VERSION case KEY_MOUSE: { MEVENT myevent; getmouse(&myevent); if (atcpu && myevent.y >= CY(0) && myevent.y <= CY(BDEPTH) && myevent.x >= CX(0) && myevent.x <= CX(BDEPTH)) { curx = CXINV(myevent.x); cury = CYINV(myevent.y); return (' '); } else { beep(); continue; } } /* no fall through */ #endif /* NCURSES_MOUSE_VERSION */ default: if (atcpu) (void) mvaddstr(CYBASE + BDEPTH + 1, CXBASE + 11, " "); else (void) mvaddstr(PYBASE + BDEPTH + 1, PXBASE + 11, " "); return (c); } curx = nx % BWIDTH; cury = ny % BDEPTH; } }
static void initgame(void) { int i, j, unplaced; ship_t *ss; (void) clear(); (void) mvaddstr(0, 35, "BATTLESHIPS"); (void) move(PROMPTLINE + 2, 0); announceopts(); memset(board, 0, sizeof(char) * BWIDTH * BDEPTH * 2); memset(hits, 0, sizeof(char) * BWIDTH * BDEPTH * 2); for (i = 0; i < SHIPTYPES; i++) { ss = cpuship + i; ss->x = ss->y = ss->dir = ss->hits = 0; ss->placed = FALSE; ss = plyship + i; ss->x = ss->y = ss->dir = ss->hits = 0; ss->placed = FALSE; } /* draw empty boards */ (void) mvaddstr(PYBASE - 2, PXBASE + 5, "Main Board"); (void) mvaddstr(PYBASE - 1, PXBASE - 3, numbers); for (i = 0; i < BDEPTH; ++i) { (void) mvaddch(PYBASE + i, PXBASE - 3, (chtype) (i + 'A')); #ifdef A_COLOR if (has_colors()) attron(COLOR_PAIR(COLOR_BLUE)); #endif /* A_COLOR */ (void) addch(' '); for (j = 0; j < BWIDTH; j++) (void) addstr(" . "); #ifdef A_COLOR (void) attrset(0); #endif /* A_COLOR */ (void) addch(' '); (void) addch((chtype) (i + 'A')); } (void) mvaddstr(PYBASE + BDEPTH, PXBASE - 3, numbers); (void) mvaddstr(CYBASE - 2, CXBASE + 7, "Hit/Miss Board"); (void) mvaddstr(CYBASE - 1, CXBASE - 3, numbers); for (i = 0; i < BDEPTH; ++i) { (void) mvaddch(CYBASE + i, CXBASE - 3, (chtype) (i + 'A')); #ifdef A_COLOR if (has_colors()) attron(COLOR_PAIR(COLOR_BLUE)); #endif /* A_COLOR */ (void) addch(' '); for (j = 0; j < BWIDTH; j++) (void) addstr(" . "); #ifdef A_COLOR (void) attrset(0); #endif /* A_COLOR */ (void) addch(' '); (void) addch((chtype) (i + 'A')); } (void) mvaddstr(CYBASE + BDEPTH, CXBASE - 3, numbers); (void) mvprintw(HYBASE, HXBASE, "To position your ships: move the cursor to a spot, then"); (void) mvprintw(HYBASE + 1, HXBASE, "type the first letter of a ship type to select it, then"); (void) mvprintw(HYBASE + 2, HXBASE, "type a direction ([hjkl] or [4862]), indicating how the"); (void) mvprintw(HYBASE + 3, HXBASE, "ship should be pointed. You may also type a ship letter"); (void) mvprintw(HYBASE + 4, HXBASE, "followed by `r' to position it randomly, or type `R' to"); (void) mvprintw(HYBASE + 5, HXBASE, "place all remaining ships randomly."); (void) mvaddstr(MYBASE, MXBASE, "Aiming keys:"); (void) mvaddstr(SYBASE, SXBASE, "y k u 7 8 9"); (void) mvaddstr(SYBASE + 1, SXBASE, " \\|/ \\|/ "); (void) mvaddstr(SYBASE + 2, SXBASE, "h-+-l 4-+-6"); (void) mvaddstr(SYBASE + 3, SXBASE, " /|\\ /|\\ "); (void) mvaddstr(SYBASE + 4, SXBASE, "b j n 1 2 3"); /* have the computer place ships */ for (ss = cpuship; ss < cpuship + SHIPTYPES; ss++) { randomplace(COMPUTER, ss); placeship(COMPUTER, ss, FALSE); } ss = (ship_t *) NULL; do { char c, docked[SHIPTYPES + 2], *cp = docked; /* figure which ships still wait to be placed */ *cp++ = 'R'; for (i = 0; i < SHIPTYPES; i++) if (!plyship[i].placed) *cp++ = plyship[i].symbol; *cp = '\0'; /* get a command letter */ prompt(1, "Type one of [%s] to pick a ship.", docked + 1); do { c = (char) getcoord(PLAYER); } while (!strchr(docked, c)); if (c == 'R') (void) ungetch('R'); else { /* map that into the corresponding symbol */ for (ss = plyship; ss < plyship + SHIPTYPES; ss++) if (ss->symbol == c) break; prompt(1, "Type one of [hjklrR] to place your %s.", ss->name); pgoto(cury, curx); } do { c = (char) getch(); } while (!(strchr("hjklrR", c) || c == FF)); if (c == FF) { (void) clearok(stdscr, TRUE); (void) refresh(); } else if (c == 'r') { assert(ss != 0); prompt(1, "Random-placing your %s", ss->name); randomplace(PLAYER, ss); placeship(PLAYER, ss, TRUE); error((char *) NULL); ss->placed = TRUE; } else if (c == 'R') { prompt(1, "Placing the rest of your fleet at random...", ""); for (ss = plyship; ss < plyship + SHIPTYPES; ss++) if (!ss->placed) { randomplace(PLAYER, ss); placeship(PLAYER, ss, TRUE); ss->placed = TRUE; } error((char *) NULL); } else if (strchr("hjkl8462", c)) { assert(ss != 0); ss->x = curx; ss->y = cury; switch (c) { case 'k': case '8': ss->dir = N; break; case 'j': case '2': ss->dir = S; break; case 'h': case '4': ss->dir = W; break; case 'l': case '6': ss->dir = E; break; } if (checkplace(PLAYER, ss, TRUE)) { placeship(PLAYER, ss, TRUE); error((char *) NULL); ss->placed = TRUE; } } for (unplaced = i = 0; i < SHIPTYPES; i++) unplaced += !plyship[i].placed; } while (unplaced); turn = rnd(2); (void) mvprintw(HYBASE, HXBASE, "To fire, move the cursor to your chosen aiming point "); (void) mvprintw(HYBASE + 1, HXBASE, "and strike any key other than a motion key. "); (void) mvprintw(HYBASE + 2, HXBASE, " "); (void) mvprintw(HYBASE + 3, HXBASE, " "); (void) mvprintw(HYBASE + 4, HXBASE, " "); (void) mvprintw(HYBASE + 5, HXBASE, " "); (void) prompt(0, "Press any key to start...", ""); (void) getch(); }
/* When called with c==-1, it just creates the prompt */ static int itype(W *w, int c, void *obj, int *notify) { IREC *i; int omid; BW *bw; struct isrch *isrch = (struct isrch *)obj; WIND_BW(bw,w); if (isrch->quote) { goto in; } if (c == 8 || c == 127) { /* Backup */ if ((i = isrch->irecs.link.prev) != &isrch->irecs) { pgoto(bw->cursor, i->disp); if (globalsrch) globalsrch->wrap_flag = i->wrap_flag; omid = opt_mid; opt_mid = 1; dofollows(); opt_mid = omid; isrch->pattern = vstrunc(isrch->pattern, sLEN(isrch->pattern) - i->what); frirec(deque_f(IREC, link, i)); } else { if(joe_beep) ttputc(7); } } else if (c == 'Q' - '@' /* || c == '`' */) { isrch->quote = 1; } else if (c == 'S' - '@' || c == '\\' - '@' || c == 'L' - '@' || c == 'R' - '@') { /* Repeat */ if (c == 'R' - '@') { isrch->dir = 1; } else { isrch->dir = 0; } if (qempty(IREC, link, &isrch->irecs)) { if (lastpat && lastpat[0]) { iappend(bw, isrch, sv(lastpat)); } } else { SRCH *srch; i = alirec(); i->disp = i->start = bw->cursor->byte; i->what = 0; if (!globalsrch) srch = mksrch(NULL,NULL,opt_icase,isrch->dir,-1,0,0,0,0); else { srch = globalsrch; globalsrch = 0; } srch->addr = bw->cursor->byte; if (!srch->wrap_p || srch->wrap_p->b!=bw->b) { prm(srch->wrap_p); srch->wrap_p = pdup(bw->cursor, "itype"); srch->wrap_p->owner = &srch->wrap_p; srch->wrap_flag = 0; } i->wrap_flag = srch->wrap_flag; setpat(srch, vsncpy(NULL, 0, isrch->pattern, sLen(isrch->pattern))); srch->backwards = isrch->dir; if (dopfnext(bw, srch, NULL)) { if(joe_beep) ttputc(7); frirec(i); } else { enqueb(IREC, link, &isrch->irecs, i); } } } else if (c >= 0 && c < 32) { /* Done when a control character is received */ nungetc(c); if (notify) { *notify = 1; } smode = 2; if (lastisrch) { lastpat = vstrunc(lastpat, 0); lastpat = vsncpy(lastpat, 0, lastisrch->pattern, sLen(lastisrch->pattern)); rmisrch(lastisrch); } lastisrch = isrch; return 0; } else if (c != -1) { char buf[16]; ptrdiff_t buf_len; /* Search */ in: if (bw->b->o.charmap->type) { buf_len = utf8_encode(buf, c); } else { buf[0] = TO_CHAR_OK(from_uni(bw->b->o.charmap, c)); buf_len = 1; } isrch->quote = 0; iappend(bw, isrch, buf, buf_len); } omid = opt_mid; opt_mid = 1; bw->cursor->xcol = piscol(bw->cursor); dofollows(); opt_mid = omid; isrch->prompt = vstrunc(isrch->prompt, isrch->ofst); if (locale_map->type && !bw->b->o.charmap->type) { /* Translate bytes to utf-8 */ char buf[16]; int x; for (x=0; x!=sLEN(isrch->pattern); ++x) { int tc = to_uni(bw->b->o.charmap, isrch->pattern[x]); utf8_encode(buf, tc); isrch->prompt = vsncpy(sv(isrch->prompt),sz(buf)); } } else if (!locale_map->type && bw->b->o.charmap->type) { /* Translate utf-8 to bytes */ const char *p = isrch->pattern; ptrdiff_t len = sLEN(isrch->pattern); while (len) { int tc = utf8_decode_fwrd(&p, &len); if (tc >= 0) { tc = from_uni(locale_map, tc); isrch->prompt = vsadd(isrch->prompt, TO_CHAR_OK(tc)); } } } else { /* FIXME: translate when charmaps do not match */ isrch->prompt = vsncpy(sv(isrch->prompt),sv(isrch->pattern)); } if (mkqwnsr(bw->parent, sv(isrch->prompt), itype, iabrt, isrch, notify)) { return 0; } else { rmisrch(isrch); return -1; } }
static int getcoord(int atcpu) { int ny, nx, c; if (atcpu) cgoto(cury,curx); else pgoto(cury, curx); refresh(); for (;;) { if (atcpu) { mvprintw(CYBASE + BDEPTH+1, CXBASE+11, "(%d, %c)", curx, 'A'+cury); cgoto(cury, curx); } else { mvprintw(PYBASE + BDEPTH+1, PXBASE+11, "(%d, %c)", curx, 'A'+cury); pgoto(cury, curx); } switch(c = getch()) { case 'k': case '8': #ifdef KEY_MIN case KEY_UP: #endif /* KEY_MIN */ ny = cury+BDEPTH-1; nx = curx; break; case 'j': case '2': #ifdef KEY_MIN case KEY_DOWN: #endif /* KEY_MIN */ ny = cury+1; nx = curx; break; case 'h': case '4': #ifdef KEY_MIN case KEY_LEFT: #endif /* KEY_MIN */ ny = cury; nx = curx+BWIDTH-1; break; case 'l': case '6': #ifdef KEY_MIN case KEY_RIGHT: #endif /* KEY_MIN */ ny = cury; nx = curx+1; break; case 'y': case '7': #ifdef KEY_MIN case KEY_A1: #endif /* KEY_MIN */ ny = cury+BDEPTH-1; nx = curx+BWIDTH-1; break; case 'b': case '1': #ifdef KEY_MIN case KEY_C1: #endif /* KEY_MIN */ ny = cury+1; nx = curx+BWIDTH-1; break; case 'u': case '9': #ifdef KEY_MIN case KEY_A3: #endif /* KEY_MIN */ ny = cury+BDEPTH-1; nx = curx+1; break; case 'n': case '3': #ifdef KEY_MIN case KEY_C3: #endif /* KEY_MIN */ ny = cury+1; nx = curx+1; break; case FF: nx = curx; ny = cury; clearok(stdscr, TRUE); refresh(); break; default: if (atcpu) mvaddstr(CYBASE + BDEPTH + 1, CXBASE + 11, " "); else mvaddstr(PYBASE + BDEPTH + 1, PXBASE + 11, " "); return(c); } curx = nx % BWIDTH; cury = ny % BDEPTH; } }