games-request@tekred.TEK.COM (05/11/87)
Submitted by: Tim Stoehr <tims@zues.TEK.COM> Comp.sources.games: Volume 1, Issue 12 Archive-name: rogue/Part02 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 2 (of 5)." # Contents: curses.c machdep.c object.c throw.c # Wrapped by billr@tekred on Mon May 11 12:19:17 1987 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f curses.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"curses.c\" else echo shar: Extracting \"curses.c\" \(11545 characters\) sed "s/^X//" >curses.c <<'END_OF_curses.c' X/* X * curses.c X * X * This source herein may be modified and/or distributed by anybody who X * so desires, with the following restrictions: X * 1.) No portion of this notice shall be removed. X * 2.) Credit shall not be taken for the creation of this source. X * 3.) This code is not to be traded, sold, or used for personal X * gain or profit. X * X */ X X#ifdef CURSES X X/* The following is a curses emulation package suitable for the rogue program X * in which it is included. No other suitability is claimed or suspected. X * Only those routines currently needed by this rogue program are included. X * This is being provided for those systems that don't have a suitable X * curses package and want to run this rogue program. X * X * Compile the entire program with -DCURSES to incorporate this package. X * X * The following is NOT supported: X * "%D", "%B", "%n", or "%>" inside a cursor motion (cm) termcap string. X * Terminals in which the cursor motion addresses the row differently from X * the column, as in ":cm=\E%2,%3" or ":cm=\EY%+x;%+y" X * Termcap database stored in the TERMCAP environ variable as returned X * from md_getenv(). Only the termcap file name can be stored there. X * See the comments for md_getenv() in machdep.c. X * Terminals without non-destructive backspace. Backspace (^H) is used X * for cursor motion regardless of any termcap entries. X * The ":tc=" termcap entry is ignored. X * X * Suggestions: X * Use line-feed as your termcap "do" entry: ":do=^J", ":do=\012" or X * ":do=\n" This will help cursor motion optimization. If line-feed X * won't work, then a short escape sequence will do. Same goes for "up" X */ X X#include <stdio.h> X#include "rogue.h" X Xboolean tc_tname(); X X#define BS 010 X#define LF 012 X#define CR 015 X#define ESC '\033' X#define TAB '\011' X X#define ST_MASK 0x80 X#define BUFLEN 256 X Xchar terminal[DROWS][DCOLS]; Xchar buffer[DROWS][DCOLS]; Xchar *tc_file; X Xchar cm_esc[16], cm_sep[16], cm_end[16]; Xboolean cm_reverse = 0; Xboolean cm_two = 0; Xboolean cm_three = 0; Xboolean cm_char = 0; Xshort cm_inc = 0; X Xboolean screen_dirty; Xboolean lines_dirty[DROWS]; Xboolean buf_stand_out = 0; Xboolean term_stand_out = 0; X Xint LINES = DROWS, COLS = DCOLS; XWINDOW scr_buf; XWINDOW *curscr = &scr_buf; X Xchar *CL = (char *) 0; Xchar *CM = (char *) 0; Xchar *UC = (char *) 0; Xchar *DO = (char *) 0; Xchar *VS = ""; Xchar *VE = ""; Xchar *TI = ""; Xchar *TE = ""; Xchar *SO = ""; Xchar *SE = ""; X Xshort cur_row, cur_col; X Xinitscr() X{ X clear(); X get_term_info(); X printf("%s%s", TI, VS); X} X Xendwin() X{ X printf("%s%s", TE, VE); X md_cbreak_no_echo_nonl(0); X} X Xmove(row, col) Xshort row, col; X{ X curscr->_cury = row; X curscr->_curx = col; X screen_dirty = 1; X} X Xmvaddstr(row, col, str) Xshort row, col; Xchar *str; X{ X move(row, col); X addstr(str); X} X Xaddstr(str) Xchar *str; X{ X while (*str) { X addch((int) *str++); X } X} X Xaddch(ch) Xregister int ch; X{ X short row, col; X X row = curscr->_cury; X col = curscr->_curx++; X X if (buf_stand_out) { X ch |= ST_MASK; X } X buffer[row][col] = (char) ch; X lines_dirty[row] = 1; X screen_dirty = 1; X} X Xmvaddch(row, col, ch) Xshort row, col; Xint ch; X{ X move(row, col); X addch(ch); X} X Xrefresh() X{ X register i, j, line; X short old_row, old_col, first_row; X X if (screen_dirty) { X X old_row = curscr->_cury; X old_col = curscr->_curx; X first_row = cur_row; X X for (i = 0; i < DROWS; i++) { X line = (first_row + i) % DROWS; X if (lines_dirty[line]) { X for (j = 0; j < DCOLS; j++) { X if (buffer[line][j] != terminal[line][j]) { X put_char_at(line, j, buffer[line][j]); X } X } X lines_dirty[line] = 0; X } X } X put_cursor(old_row, old_col); X screen_dirty = 0; X fflush(stdout); X } X} X Xwrefresh(scr) XWINDOW *scr; X{ X short i, col; X X printf("%s", CL); X cur_row = cur_col = 0; X X for (i = 0; i < DROWS; i++) { X col = 0; X while (col < DCOLS) { X while ((col < DCOLS) && (buffer[i][col] == ' ')) { X col++; X } X if (col < DCOLS) { X put_cursor(i, col); X } X while ((col < DCOLS) && (buffer[i][col] != ' ')) { X put_st_char((int) buffer[i][col]); X cur_col++; X col++; X } X } X } X put_cursor(curscr->_cury, curscr->_curx); X fflush(stdout); X scr = scr; /* make lint happy */ X} X Xmvinch(row, col) Xshort row, col; X{ X move(row, col); X return((int) buffer[row][col]); X} X Xclear() X{ X printf("%s", CL); X fflush(stdout); X cur_row = cur_col = 0; X move(0, 0); X clear_buffers(); X} X Xclrtoeol() X{ X short row, col; X X row = curscr->_cury; X X for (col = curscr->_curx; col < DCOLS; col++) { X buffer[row][col] = ' '; X } X lines_dirty[row] = 1; X} X Xstandout() X{ X buf_stand_out = 1; X} X Xstandend() X{ X buf_stand_out = 0; X} X Xcrmode() X{ X md_cbreak_no_echo_nonl(1); X} X Xnoecho() X{ X /* crmode() takes care of this */ X} X Xnonl() X{ X /* crmode() takes care of this */ X} X Xclear_buffers() X{ X register i, j; X X screen_dirty = 0; X X for (i = 0; i < DROWS; i++) { X lines_dirty[i] = 0; X for (j = 0; j < DCOLS; j++) { X terminal[i][j] = ' '; X buffer[i][j] = ' '; X } X } X} X Xput_char_at(row, col, ch) Xregister row, col, ch; X{ X put_cursor(row, col); X put_st_char(ch); X terminal[row][col] = (char) ch; X cur_col++; X} X Xput_cursor(row, col) Xregister row, col; X{ X register i, rdif, cdif; X short ch, t; X X rdif = (row > cur_row) ? row - cur_row : cur_row - row; X cdif = (col > cur_col) ? col - cur_col : cur_col - col; X X if (((row > cur_row) && DO) || ((cur_row > row) && UC)) { X if ((rdif < 4) && (cdif < 4)) { X for (i = 0; i < rdif; i++) { X printf("%s", ((row < cur_row) ? UC : DO)); X } X cur_row = row; X if (col == cur_col) { X return; X } X } X } X if (row == cur_row) { X if (cdif <= 6) { X for (i = 0; i < cdif; i++) { X ch = (col < cur_col) ? BS : X terminal[row][cur_col + i]; X put_st_char((int) ch); X } X cur_row = row; X cur_col = col; X return; X } X } X cur_row = row; X cur_col = col; X X row += cm_inc; X col += cm_inc; X X if (cm_reverse) { X t = row; X row = col; X col = t; X } X if (cm_two) { X printf("%s%02d%s%02d%s", cm_esc, row, cm_sep, col, cm_end); X } else if (cm_three) { X printf("%s%03d%s%03d%s", cm_esc, row, cm_sep, col, cm_end); X } else if (cm_char) { X printf("%s%c%s%c%s", cm_esc, row, cm_sep, col, cm_end); X } else { X printf("%s%d%s%d%s", cm_esc, row, cm_sep, col, cm_end); X } X} X Xput_st_char(ch) Xregister ch; X{ X if ((ch & ST_MASK) && (!term_stand_out)) { X ch &= ~ST_MASK; X printf("%s%c", SO, ch); X term_stand_out = 1; X } else if ((!(ch & ST_MASK)) && term_stand_out) { X printf("%s%c", SE, ch); X term_stand_out = 0; X } else { X ch &= ~ST_MASK; X putchar(ch); X } X} X Xget_term_info() X{ X FILE *fp; X char *term, *tcf; X char buf[BUFLEN]; X X if (tcf = md_getenv("TERMCAP")) { X if (strlen(tcf) > 40) { X clean_up("TERMCAP file name too long"); X } X tc_file = tcf; X } else { X if (!(tc_file = md_gdtcf())) { X clean_up("I need a termcap file"); X } X } X X if (!(term = md_getenv("TERM"))) { X clean_up("Cannot find TERM variable in environ"); X } X if ((fp = fopen(tc_file, "r")) == NULL) { X sprintf(buf, "Cannot open TERMCAP file: %s", tc_file); X clean_up(buf); X } X X if (!tc_tname(fp, term, buf)) { X sprintf(buf, "Cannot find TERM type: %s in TERMCAP file: %s", term, X tc_file); X clean_up(buf); X } X tc_gtdata(fp, buf); X fclose(fp); X} X Xboolean Xtc_tname(fp, term, buf) XFILE *fp; Xchar *term; Xchar *buf; X{ X short i, j; X boolean found = 0; X char *fg; X X while (!found) { X i = 0; X fg = fgets(buf, BUFLEN, fp); X if (fg != NULL) { X if ( (buf[0] != '#') && (buf[0] != ' ') && (buf[0] != TAB) && X (buf[0] != CR) && (buf[0] != LF)) { X while (buf[i] && (!found)) { X j = 0; X while (buf[i] == term[j]) { X i++; X j++; X } X if ((!term[j]) && ((buf[i] == '|') || (buf[i] == ':'))) { X found = 1; X } else { X while (buf[i] && (buf[i] != '|') && (buf[i] != ':')) { X i++; X } X if (buf[i]) { X i++; X } X } X } X } X } else { X break; X } X } X return(found); X} X Xtc_gtdata(fp, buf) XFILE *fp; Xchar *buf; X{ X short i; X boolean first = 1; X X do { X if (!first) { X if ((buf[0] != TAB) && (buf[0] != ' ')) { X break; X } X } X first = 0; X i = 0; X while (buf[i]) { X while (buf[i] && (buf[i] != ':')) { X i++; X } X if (buf[i] == ':') { X if (!strncmp(buf + i, ":cl=", 4)) { X tc_gets(buf + i, &CL); X } else if (!strncmp(buf + i, ":cm=", 4)) { X tc_gets(buf + i, &CM); X } else if (!strncmp(buf + i, ":up=", 4)) { X tc_gets(buf + i, &UC); X } else if (!strncmp(buf + i, ":do=", 4)) { X tc_gets(buf + i, &DO); X } else if (!strncmp(buf + i, ":vs=", 4)) { X tc_gets(buf + i, &VS); X } else if (!strncmp(buf + i, ":ve=", 4)) { X tc_gets(buf + i, &VE); X } else if (!strncmp(buf + i, ":ti=", 4)) { X tc_gets(buf + i, &TI); X } else if (!strncmp(buf + i, ":te=", 4)) { X tc_gets(buf + i, &TE); X } else if (!strncmp(buf + i, ":vs=", 4)) { X tc_gets(buf + i, &VS); X } else if (!strncmp(buf + i, ":ve=", 4)) { X tc_gets(buf + i, &VE); X } else if (!strncmp(buf + i, ":so=", 4)) { X tc_gets(buf + i, &SO); X } else if (!strncmp(buf + i, ":se=", 4)) { X tc_gets(buf + i, &SE); X } else if (!strncmp(buf + i, ":li#", 4)) { X tc_gnum(buf + i, &LINES); X } else if (!strncmp(buf + i, ":co#", 4)) { X tc_gnum(buf + i, &COLS); X } X i++; X } X } X } while (fgets(buf, BUFLEN, fp) != NULL); X X if ((!CM) || (!CL)) { X clean_up("Terminal and termcap must have cm and cl"); X } X tc_cmget(); X} X Xtc_gets(ibuf, tcstr) Xchar *ibuf; Xchar **tcstr; X{ X short i, j, k, n; X char obuf[BUFLEN]; X X i = 4; X j = 0; X X while (ibuf[i] && is_digit(ibuf[i])) { X i++; X } X X while (ibuf[i] && (ibuf[i] != ':')) { X if (ibuf[i] == '\\') { X i++; X switch(ibuf[i]) { X case 'E': X obuf[j] = ESC; X i++; X break; X case 'n': X obuf[j] = LF; X i++; X break; X case 'r': X obuf[j] = CR; X i++; X break; X case 'b': X obuf[j] = BS; X i++; X break; X case 't': X obuf[j] = TAB; X i++; X break; X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X n = 0; X k = 0; X while (k < 3 && ibuf[i] && is_digit(ibuf[i])) { X n = (8 * n) + (ibuf[i] - '0'); X i++; X k++; X } X obuf[j] = (char) n; X break; X default: X obuf[j] = ibuf[i]; X i++; X } X } else if (ibuf[i] == '^') { X obuf[j] = ibuf[i+1] - 64; X i += 2; X } else { X obuf[j] = ibuf[i++]; X } X j++; X } X obuf[j] = 0; X if (!(*tcstr = md_malloc(j + 1))) { X clean_up("cannot alloc() memory"); X } X strcpy(*tcstr, obuf); X} X Xtc_gnum(ibuf, n) Xchar *ibuf; Xint *n; X{ X short i; X int r = 0; X X i = 4; X X while (is_digit(ibuf[i])) { X r = (r * 10) + (ibuf[i] - '0'); X i++; X } X *n = r; X} X Xtstp() X{ X endwin(); X md_tstp(); X X start_window(); X printf("%s%s", TI, VS); X wrefresh(curscr); X md_slurp(); X} X Xtc_cmget() X{ X short i = 0, j = 0, rc_spec = 0; X X while (CM[i] && (CM[i] != '%') && (j < 15)) { X cm_esc[j++] = CM[i++]; X } X cm_esc[j] = 0; X X while (CM[i] && (rc_spec < 2)) { X if (CM[i] == '%') { X i++; X switch(CM[i]) { X case 'd': X rc_spec++; X break; X case 'i': X cm_inc = 1; X break; X case '2': X cm_two = 1; X rc_spec++; X break; X case '3': X cm_three = 1; X rc_spec++; X break; X case '.': X cm_char = 1; X rc_spec++; X break; X case 'r': X cm_reverse = 1; X break; X case '+': X i++; X cm_inc = CM[i]; X cm_char = 1; X rc_spec++; X break; X } X i++; X } else { X j = 0; X while (CM[i] && (CM[i] != '%')) { X cm_sep[j++] = CM[i++]; X } X cm_sep[j] = 0; X } X } X X j = 0; X if (rc_spec == 2) { X while (CM[i] && (j < 15)) { X cm_end[j++] = CM[i++]; X } X } X cm_end[j] = 0; X} X X#endif CURSES END_OF_curses.c if test 11545 -ne `wc -c <curses.c`; then echo shar: \"curses.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f machdep.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"machdep.c\" else echo shar: Extracting \"machdep.c\" \(15393 characters\) sed "s/^X//" >machdep.c <<'END_OF_machdep.c' X/* X * machdep.c X * X * This source herein may be modified and/or distributed by anybody who X * so desires, with the following restrictions: X * 1.) No portion of this notice shall be removed. X * 2.) Credit shall not be taken for the creation of this source. X * 3.) This code is not to be traded, sold, or used for personal X * gain or profit. X * X */ X X/* Included in this file are all system dependent routines. Extensive use X * of #ifdef's will be used to compile the appropriate code on each system: X * X * UNIX: all UNIX systems. X * UNIX_BSD4_2: UNIX BSD 4.2 and later, UTEK, (4.1 BSD too?) X * UNIX_SYS5: UNIX system 5 X * UNIX_V7: UNIX version 7 X * X * All UNIX code should be included between the single "#ifdef UNIX" at the X * top of this file, and the "#endif UNIX" at the bottom. X * X * To change a routine to include a new UNIX system, simply #ifdef the X * existing routine, as in the following example: X * X * To make a routine compatible with UNIX system 5, change the first X * function to the second: X * X * md_function() X * { X * code; X * } X * X * md_function() X * { X * #ifdef UNIX_SYS5 X * sys5code; X * #else X * code; X * #endif X * } X * X * Appropriate variations of this are of course acceptible. X * The use of "#elseif" is discouraged because of non-portability. X * If the correct #define doesn't exist, "UNIX_SYS5" in this case, make it up X * and insert it in the list at the top of the file. Alter the CFLAGS X * in you Makefile appropriately. X * X */ X X#ifdef UNIX X X#include <stdio.h> X#include <sgtty.h> X#include <sys/file.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <sys/time.h> X#include <signal.h> X#include "rogue.h" X X/* md_slurp: X * X * This routine throws away all keyboard input that has not X * yet been read. It is used to get rid of input that the user may have X * typed-ahead. X * X * This function is not necessary, so it may be stubbed. The might cause X * message-line output to flash by because the game has continued to read X * input without waiting for the user to read the message. Not such a X * big deal. X */ X Xmd_slurp() X{ X#ifdef UNIX_BSD4_2 X long ln; X int i, n; X ioctl(0, FIONREAD, &ln); X n = (int) (stdin->_cnt + ln); X X for (i = 0; i < n; i++) { X (void) getchar(); X } X#endif UNIX_BSD4_2 X} X X/* md_control_keyboard(): X * X * This routine is much like md_cbreak_no_echo_nonl() above. It sets up the X * keyboard for appropriate input. Specifically, it prevents the tty driver X * from stealing characters. For example, ^Y is needed as a command X * character, but the tty driver intercepts it for another purpose. Any X * such behavior should be stopped. This routine could be avoided if X * we used RAW mode instead of CBREAK. But RAW mode does not allow the X * generation of keyboard signals, which the program uses. X * X * The parameter 'mode' when true, indicates that the keyboard should X * be set up to play rogue. When false, it should be restored if X * necessary. X * X * This routine is not strictly necessary and may be stubbed. This may X * cause certain command characters to be unavailable. X */ X Xmd_control_keybord(mode) Xshort mode; X{ X static boolean called_before = 0; X static struct ltchars ltc_orig; X static struct tchars tc_orig; X struct ltchars ltc_temp; X struct tchars tc_temp; X X if (!called_before) { X called_before = 1; X ioctl(0, TIOCGETC, &tc_orig); X ioctl(0, TIOCGLTC, <c_orig); X } X ltc_temp = ltc_orig; X tc_temp = tc_orig; X X if (!mode) { X#ifdef UNIX_BSD4_2 X ltc_temp.t_suspc = ltc_temp.t_dsuspc = -1; X#endif UNIX_BSD4_2 X ltc_temp.t_rprntc = ltc_temp.t_flushc = -1; X ltc_temp.t_werasc = ltc_temp.t_lnextc = -1; X tc_temp.t_startc = tc_temp.t_stopc = -1; X } X ioctl(0, TIOCSETC, &tc_temp); X ioctl(0, TIOCSLTC, <c_temp); X} X X/* md_heed_signals(): X * X * This routine tells the program to call particular routines when X * certain interrupts/events occur: X * X * SIGINT: call onintr() to interrupt fight with monster or long rest. X * SIGQUIT: call byebye() to check for game termination. X * SIGHUP: call error_save() to save game when terminal hangs up. X * X * On VMS, SIGINT and SIGQUIT correspond to ^C and ^Y. X * X * This routine is not strictly necessary and can be stubbed. This will X * mean that the game cannot be interrupted properly with keyboard X * input, this is not usually critical. X */ X Xmd_heed_signals() X{ X signal(SIGINT, onintr); X signal(SIGQUIT, byebye); X signal(SIGHUP, error_save); X} X X/* md_ignore_signals(): X * X * This routine tells the program to completely ignore the events mentioned X * in md_heed_signals() above. The event handlers will later be turned on X * by a future call to md_heed_signals(), so md_heed_signals() and X * md_ignore_signals() need to work together. X * X * This function should be implemented or the user risks interrupting X * critical sections of code, which could cause score file, or saved-game X * file, corruption. X */ X Xmd_ignore_signals() X{ X signal(SIGQUIT, SIG_IGN); X signal(SIGINT, SIG_IGN); X signal(SIGHUP, SIG_IGN); X} X X/* md_get_file_id(): X * X * This function returns an integer that uniquely identifies the specified X * file. It need not check for the file's existence. In UNIX, the inode X * number is used. X * X * This function need not be implemented. To stub the routine, just make X * it return 0. This will make the game less able to prevent users from X * modifying saved-game files. This is probably no big deal. X */ X Xint Xmd_get_file_id(fname) Xchar *fname; X{ X struct stat sbuf; X X if (stat(fname, &sbuf)) { X return(-1); X } X return((int) sbuf.st_ino); X} X X/* md_link_count(): X * X * This routine returns the number of hard links to the specified file. X * X * This function is not strictly necessary. On systems without hard links X * this routine can be stubbed by just returning 1. X */ X Xint Xmd_link_count(fname) Xchar *fname; X{ X struct stat sbuf; X X stat(fname, &sbuf); X return((int) sbuf.st_nlink); X} X X/* md_gct(): (Get Current Time) X * X * This function returns the current year, month(1-12), day(1-31), hour(0-23), X * minute(0-59), and second(0-59). This is used for identifying the time X * at which a game is saved. X * X * This function is not strictly necessary. It can be stubbed by returing X * zeros instead of the correct year, month, etc. If your operating X * system doesn't provide all of the time units requested here, then you X * can provide only those that it does, and return zeros for the others. X * If you cannot provide good time values, then users may be able to copy X * saved-game files and play them. X */ X Xmd_gct(rt_buf) Xstruct rogue_time *rt_buf; X{ X struct timeval tv; X struct timezone tzp; X struct tm *t; X long seconds; X X gettimeofday(&tv, &tzp); X seconds = (long) tv.tv_sec; X t = localtime(&seconds); X X rt_buf->year = t->tm_year; X rt_buf->month = t->tm_mon + 1; X rt_buf->day = t->tm_mday; X rt_buf->hour = t->tm_hour; X rt_buf->minute = t->tm_min; X rt_buf->second = t->tm_sec; X} X X/* md_gfmt: (Get File Modification Time) X * X * This routine returns a file's date of last modification in the same format X * as md_gct() above. X * X * This function is not strictly necessary. It is used to see if saved-game X * files have been modified since they were saved. If you have stubbed the X * routine md_gct() above by returning constant values, then you may do X * exactly the same here. X * Or if md_gct() is implemented correctly, but your system does not provide X * file modification dates, you may return some date far in the past so X * that the program will never know that a saved-game file being modified. X * You may also do this if you wish to be able to restore games from X * saved-games that have been modified. X */ X Xmd_gfmt(fname, rt_buf) Xchar *fname; Xstruct rogue_time *rt_buf; X{ X struct stat sbuf; X long seconds; X struct tm *t; X X stat(fname, &sbuf); X seconds = (long) sbuf.st_mtime; X t = localtime(&seconds); X X rt_buf->year = t->tm_year; X rt_buf->month = t->tm_mon + 1; X rt_buf->day = t->tm_mday; X rt_buf->hour = t->tm_hour; X rt_buf->minute = t->tm_min; X rt_buf->second = t->tm_sec; X} X X/* md_df: (Delete File) X * X * This function deletes the specified file, and returns true (1) if the X * operation was successful. This is used to delete saved-game files X * after restoring games from them. X * X * Again, this function is not strictly necessary, and can be stubbed X * by simply returning 1. In this case, saved-game files will not be X * deleted and can be replayed. X */ X Xboolean Xmd_df(fname) Xchar *fname; X{ X if (unlink(fname)) { X return(0); X } X return(1); X} X X/* md_gln: (Get login name) X * X * This routine returns the login name of the user. This string is X * used mainly for identifying users in score files. X * X * A dummy string may be returned if you are unable to implement this X * function, but then the score file would only have one name in it. X */ X Xchar * Xmd_gln() X{ X char *getlogin(); X char *t; X X t = getlogin(); X return(t); X} X X/* md_sleep: X * X * This routine causes the game to pause for the specified number of X * seconds. X * X * This routine is not necessary at all, and can be stubbed with no ill X * effects. X */ X Xmd_sleep(nsecs) Xint nsecs; X{ X (void) sleep(nsecs); X} X X/* md_getenv() X * X * This routine gets certain values from the user's environment. These X * values are strings, and each string is identified by a name. The names X * of the values needed, and their use, is as follows: X * X * TERMCAP X * The name of the users's termcap file, NOT the termcap entries X * themselves. This is used ONLY if the program is compiled with X * CURSES defined (-DCURSES). Even in this case, the program need X * not find a string for TERMCAP. If it does not, it will use the X * default termcap file as returned by md_gdtcf(); X * TERM X * The name of the users's terminal. This is used ONLY if the program X * is compiled with CURSES defined (-DCURSES). In this case, the string X * value for TERM must be found, or the routines in curses.c cannot X * function, and the program will quit. X * ROGUEOPTS X * A string containing the various game options. This need not be X * defined. X * HOME X * The user's home directory. This is only used when the user specifies X * '~' as the first character of a saved-game file. This string need X * not be defined. X * X * If your system does not provide a means of searching for these values, X * you will have to do it yourself. None of the values above really need X * to be defined except TERM when the program is compiled with CURSES X * defined. In this case, as a bare minimum, you can check the 'name' X * parameter, and if it is "TERM" find the terminal name and return that, X * else return zero. If the program is not compiled with CURSES, you can X * get by with simply always returning zero. Returning zero indicates X * that their is no defined value for the given string. X */ X Xchar * Xmd_getenv(name) Xchar *name; X{ X char *value; X char *getenv(); X X value = getenv(name); X X return(value); X} X X/* md_malloc() X * X * This routine allocates, and returns a pointer to, the specified number X * of bytes. This routines absolutely MUST be implemented for your X * particular system or the program will not run at all. Return zero X * when no more memory can be allocated. X */ X Xchar * Xmd_malloc(n) Xint n; X{ X char *malloc(); X char *t; X X t = malloc(n); X return(t); X} X X/* md_gseed() (Get Seed) X * X * This function returns a seed for the random number generator (RNG). This X * seed causes the RNG to begin generating numbers at some point in it's X * sequence. Without a random seed, the RNG will generate the same set X * of numbers, and every game will start out exactly the same way. A good X * number to use is the process id, given by getpid() on most UNIX systems. X * X * You need to find some single random integer, such as: X * process id. X * current time (minutes + seconds) returned from md_gct(), if implemented. X * X * It will not help to return "get_rand()" or "rand()" or the return value of X * any pseudo-RNG. If you cannot a random number, you can just return 1, X * but this means you games will ALWAYS start the same way, and will play X * exactly the same way given the same input. X */ X Xmd_gseed() X{ X return(getpid()); X} X X/* md_exit(): X * X * This function causes the program to discontinue execution and exit. X * This function must be implemented or the program will continue to X * hang when it should quit. X */ X Xmd_exit(status) Xint status; X{ X exit(status); X} X X/* If you have a viable curses/termlib library, then use it and don't bother X * implementing the routines below. And don't compile with -DCURSES. X */ X X#ifdef CURSES X X/* md_cbreak_no_echo_nonl: X * X * This routine sets up some terminal characteristics. The tty-driver X * must be told to: X * 1.) Not echo input. X * 2.) Transmit input characters immediately upon typing. (cbreak mode) X * 3.) Move the cursor down one line, without changing column, and X * without generating a carriage-return, when it X * sees a line-feed. This is only necessary if line-feed is ever X * used in the termcap 'do' (cursor down) entry, in which case, X * your system should must have a way of accomplishing this. X * X * When the parameter 'on' is true, the terminal is set up as specified X * above. When this parameter is false, the terminal is restored to the X * original state. X * X * Raw mode should not to be used. Keyboard signals/events/interrupts should X * be sent, although they are not strictly necessary. See notes in X * md_heed_signals(). X * X * This function must be implemented for rogue to run properly if the X * program is compiled with CURSES defined to use the enclosed curses X * emulation package. If you are not using this, then this routine is X * totally unnecessary. X * X * Notice that information is saved between calls. This is used to X * restore the terminal to an initial saved state. X * X */ X Xmd_cbreak_no_echo_nonl(on) Xboolean on; X{ X static struct sgttyb tty_buf; X static int tty_save_flags; X X if (on) { X ioctl(0, TIOCGETP, &tty_buf); X tty_save_flags = tty_buf.sg_flags; X tty_buf.sg_flags |= CBREAK; X tty_buf.sg_flags &= ~(ECHO | CRMOD); /* CRMOD: see note above */ X ioctl(0, TIOCSETP, &tty_buf); X } else { X tty_buf.sg_flags = tty_save_flags; X ioctl(0, TIOCSETP, &tty_buf); X } X} X X/* md_gdtcf(): (Get Default Termcap File) X * X * This function is called ONLY when the program is compiled with CURSES X * defined. If you use your system's curses/termlib library, this function X * won't be called. On most UNIX systems, "/etc/termcap" suffices. X * X * If their is no such termcap file, then return 0, but in that case, you X * must have a TERMCAP file returned from md_getenv("TERMCAP"). The latter X * will override the value returned from md_gdtcf(). If the program is X * compiled with CURSES defined, and md_gdtcf() returns 0, and X * md_getenv("TERMCAP") returns 0, the program will have no terminal X * capability information and will quit. X */ X Xchar * Xmd_gdtcf() X{ X return("/etc/termcap"); X} X X/* md_tstp(): X * X * This function puts the game to sleep and returns to the shell. This X * only applies to UNIX 4.2 and 4.3. For other systems, the routine should X * be provided as a do-nothing routine. md_tstp() will only be referenced X * in the code when compiled with CURSES defined. X * X */ X Xmd_tstp() X{ X#ifdef UNIX_BSD4_2 X kill(0, SIGTSTP); X#endif UNIX_BSD4_2 X} X X#endif CURSES X X#endif UNIX END_OF_machdep.c if test 15393 -ne `wc -c <machdep.c`; then echo shar: \"machdep.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f object.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"object.c\" else echo shar: Extracting \"object.c\" \(16345 characters\) sed "s/^X//" >object.c <<'END_OF_object.c' X/* X * object.c X * X * This source herein may be modified and/or distributed by anybody who X * so desires, with the following restrictions: X * 1.) No portion of this notice shall be removed. X * 2.) Credit shall not be taken for the creation of this source. X * 3.) This code is not to be traded, sold, or used for personal X * gain or profit. X * X */ X X#ifndef CURSES X#include <curses.h> X#endif CURSES X#include "rogue.h" X Xobject level_objects; Xunsigned short dungeon[DROWS][DCOLS]; Xshort foods = 0; Xshort party_counter; Xobject *free_list = (object *) 0; Xchar *fruit = "slime-mold "; X Xfighter rogue = { X 0, 0, /* armor, weapon */ X 0, 0, /* rings */ X INIT_HP, /* Hp current */ X INIT_HP, /* Hp max */ X 16, 16, /* Str */ X {0}, /* pack */ X 0, /* gold */ X 1, 0, /* exp, exp_points */ X 0, 0, /* row, col */ X '@', /* char */ X 1250 /* moves */ X}; X Xstruct id id_potions[POTIONS] = { X{100, "blue \0 ", "of increase strength ", 0}, X{250, "red \0 ", "of restore strength ", 0}, X{100, "green \0 ", "of healing ", 0}, X{200, "grey \0 ", "of extra healing ", 0}, X {10, "brown \0 ", "of poison ", 0}, X{300, "clear \0 ", "of raise level ", 0}, X {10, "pink \0 ", "of blindness ", 0}, X {25, "white \0 ", "of hallucination ", 0}, X{100, "purple \0 ", "of detect monster ", 0}, X{100, "black \0 ", "of detect things ", 0}, X {10, "yellow \0 ", "of confusion ", 0}, X {80, "plaid \0 ", "of levitation ", 0}, X{150, "burgundy \0 ", "of haste self ", 0}, X{145, "beige \0 ", "of see invisible ", 0} X}; X Xstruct id id_scrolls[SCROLLS] = { X{505, " ", "of protect armor ", 0}, X{200, " ", "of hold monster ", 0}, X{235, " ", "of enchant weapon ", 0}, X{235, " ", "of enchant armor ", 0}, X{175, " ", "of identify ", 0}, X{190, " ", "of teleportation ", 0}, X {25, " ", "of sleep ", 0}, X{610, " ", "of scare monster ", 0}, X{210, " ", "of remove curse ", 0}, X{100, " ", "of create monster ",0}, X {25, " ", "of aggravate monster ",0}, X{180, " ", "of magic mapping ",0} X}; X Xstruct id id_weapons[WEAPONS] = { X {150, "short bow ", "", 0}, X {8, "darts ", "", 0}, X {15, "arrows ", "", 0}, X {27, "daggers ", "", 0}, X {35, "shurikens ", "", 0}, X {360, "mace ", "", 0}, X {470, "long sword ", "", 0}, X {580, "two-handed sword ", "", 0} X}; X Xstruct id id_armors[ARMORS] = { X {300, "leather armor ", "", (UNIDENTIFIED)}, X {300, "ring mail ", "", (UNIDENTIFIED)}, X {400, "scale mail ", "", (UNIDENTIFIED)}, X {500, "chain mail ", "", (UNIDENTIFIED)}, X {600, "banded mail ", "", (UNIDENTIFIED)}, X {600, "splint mail ", "", (UNIDENTIFIED)}, X {700, "plate mail ", "", (UNIDENTIFIED)} X}; X Xstruct id id_wands[WANDS] = { X {25, " ", "of teleport away ",0}, X {50, " ", "of slow monster ", 0}, X {45, " ", "of confuse monster ",0}, X {8, " ", "of invisibility ",0}, X {55, " ", "of polymorph ",0}, X {2, " ", "of haste monster ",0}, X {25, " ", "of sleep ",0}, X {20, " ", "of magic missile ",0}, X {20, " ", "of cancellation ",0}, X {0, " ", "of do nothing ",0} X}; X Xstruct id id_rings[RINGS] = { X {250, " ", "of stealth ",0}, X {100, " ", "of teleportation ", 0}, X {255, " ", "of regeneration ",0}, X {295, " ", "of slow digestion ",0}, X {200, " ", "of add strength ",0}, X {250, " ", "of sustain strength ",0}, X {250, " ", "of dexterity ",0}, X {25, " ", "of adornment ",0}, X {300, " ", "of see invisible ",0}, X {290, " ", "of maintain armor ",0}, X {270, " ", "of searching ",0}, X}; X Xextern short cur_level, max_level; Xextern short party_room; Xextern char *error_file; Xextern boolean is_wood[]; X Xput_objects() X{ X short i, n; X object *obj; X X if (cur_level < max_level) { X return; X } X n = coin_toss() ? get_rand(2, 4) : get_rand(3, 5); X while (rand_percent(33)) { X n++; X } X if (cur_level == party_counter) { X make_party(); X party_counter = next_party(); X } X for (i = 0; i < n; i++) { X obj = gr_object(); X rand_place(obj); X } X put_gold(); X} X Xput_gold() X{ X short i, j; X short row,col; X boolean is_maze, is_room; X X for (i = 0; i < MAXROOMS; i++) { X is_maze = (rooms[i].is_room & R_MAZE) ? 1 : 0; X is_room = (rooms[i].is_room & R_ROOM) ? 1 : 0; X X if (!(is_room || is_maze)) { X continue; X } X if (is_maze || rand_percent(GOLD_PERCENT)) { X for (j = 0; j < 50; j++) { X row = get_rand(rooms[i].top_row+1, X rooms[i].bottom_row-1); X col = get_rand(rooms[i].left_col+1, X rooms[i].right_col-1); X if ((dungeon[row][col] == FLOOR) || X (dungeon[row][col] == TUNNEL)) { X plant_gold(row, col, is_maze); X break; X } X } X } X } X} X Xplant_gold(row, col, is_maze) Xshort row, col; Xboolean is_maze; X{ X object *obj; X X obj = alloc_object(); X obj->row = row; obj->col = col; X obj->what_is = GOLD; X obj->quantity = get_rand((2 * cur_level), (16 * cur_level)); X if (is_maze) { X obj->quantity += obj->quantity / 2; X } X dungeon[row][col] |= OBJECT; X (void) add_to_pack(obj, &level_objects, 0); X} X Xplace_at(obj, row, col) Xobject *obj; X{ X obj->row = row; X obj->col = col; X dungeon[row][col] |= OBJECT; X (void) add_to_pack(obj, &level_objects, 0); X} X Xobject * Xobject_at(pack, row, col) Xregister object *pack; Xshort row, col; X{ X object *obj; X X obj = pack->next_object; X X while (obj && ((obj->row != row) || (obj->col != col))) { X obj = obj->next_object; X } X return(obj); X} X Xobject * Xget_letter_object(ch) X{ X object *obj; X X obj = rogue.pack.next_object; X X while (obj && (obj->ichar != ch)) { X obj = obj->next_object; X } X return(obj); X} X Xfree_stuff(objlist) Xobject *objlist; X{ X object *obj; X X while (objlist->next_object) { X obj = objlist->next_object; X objlist->next_object = X objlist->next_object->next_object; X free_object(obj); X } X} X Xfree_free_list() X{ X object *obj; X X while (free_list) { X obj = free_list; X free_list = free_list->next_object; X free_object(obj); X } X} X Xchar * Xname_of(obj) Xobject *obj; X{ X char *retstring; X X switch(obj->what_is) { X case SCROLL: X retstring = obj->quantity > 1 ? "scrolls " : "scroll "; X break; X case POTION: X retstring = obj->quantity > 1 ? "potions " : "potion "; X break; X case FOOD: X if (obj->which_kind == RATION) { X retstring = "food "; X } else { X retstring = fruit; X } X break; X case WAND: X retstring = is_wood[obj->which_kind] ? "staff " : "wand "; X break; X case WEAPON: X switch(obj->which_kind) { X case DART: X retstring=obj->quantity > 1 ? "darts " : "dart "; X break; X case ARROW: X retstring=obj->quantity > 1 ? "arrows " : "arrow "; X break; X case DAGGER: X retstring=obj->quantity > 1 ? "daggers " : "dagger "; X break; X case SHURIKEN: X retstring=obj->quantity > 1?"shurikens ":"shuriken "; X break; X default: X retstring = id_weapons[obj->which_kind].title; X } X break; X case ARMOR: X retstring = "armor "; X break; X case RING: X retstring = "ring "; X break; X case AMULET: X retstring = "amulet "; X break; X default: X retstring = "unknown "; X break; X } X return(retstring); X} X Xobject * Xgr_object() X{ X object *obj; X X obj = alloc_object(); X X if (foods < (cur_level / 3)) { X obj->what_is = FOOD; X foods++; X } else { X obj->what_is = gr_what_is(); X } X switch(obj->what_is) { X case SCROLL: X gr_scroll(obj); X break; X case POTION: X gr_potion(obj); X break; X case WEAPON: X gr_weapon(obj, 1); X break; X case ARMOR: X gr_armor(obj); X break; X case WAND: X gr_wand(obj); X break; X case FOOD: X get_food(obj, 0); X break; X case RING: X gr_ring(obj, 1); X break; X } X return(obj); X} X Xunsigned short Xgr_what_is() X{ X short percent; X unsigned short what_is; X X percent = get_rand(1, 91); X X if (percent <= 30) { X what_is = SCROLL; X } else if (percent <= 60) { X what_is = POTION; X } else if (percent <= 64) { X what_is = WAND; X } else if (percent <= 74) { X what_is = WEAPON; X } else if (percent <= 83) { X what_is = ARMOR; X } else if (percent <= 88) { X what_is = FOOD; X } else { X what_is = RING; X } X return(what_is); X} X Xgr_scroll(obj) Xobject *obj; X{ X short percent; X X percent = get_rand(0, 85); X X obj->what_is = SCROLL; X X if (percent <= 5) { X obj->which_kind = PROTECT_ARMOR; X } else if (percent <= 11) { X obj->which_kind = HOLD_MONSTER; X } else if (percent <= 20) { X obj->which_kind = CREATE_MONSTER; X } else if (percent <= 35) { X obj->which_kind = IDENTIFY; X } else if (percent <= 43) { X obj->which_kind = TELEPORT; X } else if (percent <= 50) { X obj->which_kind = SLEEP; X } else if (percent <= 55) { X obj->which_kind = SCARE_MONSTER; X } else if (percent <= 64) { X obj->which_kind = REMOVE_CURSE; X } else if (percent <= 69) { X obj->which_kind = ENCH_ARMOR; X } else if (percent <= 74) { X obj->which_kind = ENCH_WEAPON; X } else if (percent <= 80) { X obj->which_kind = AGGRAVATE_MONSTER; X } else { X obj->which_kind = MAGIC_MAPPING; X } X} X Xgr_potion(obj) Xobject *obj; X{ X short percent; X X percent = get_rand(1, 118); X X obj->what_is = POTION; X X if (percent <= 5) { X obj->which_kind = RAISE_LEVEL; X } else if (percent <= 15) { X obj->which_kind = DETECT_OBJECTS; X } else if (percent <= 25) { X obj->which_kind = DETECT_MONSTER; X } else if (percent <= 35) { X obj->which_kind = INCREASE_STRENGTH; X } else if (percent <= 45) { X obj->which_kind = RESTORE_STRENGTH; X } else if (percent <= 55) { X obj->which_kind = HEALING; X } else if (percent <= 65) { X obj->which_kind = EXTRA_HEALING; X } else if (percent <= 75) { X obj->which_kind = BLINDNESS; X } else if (percent <= 85) { X obj->which_kind = HALLUCINATION; X } else if (percent <= 95) { X obj->which_kind = CONFUSION; X } else if (percent <= 105) { X obj->which_kind = POISON; X } else if (percent <= 110) { X obj->which_kind = LEVITATION; X } else if (percent <= 114) { X obj->which_kind = HASTE_SELF; X } else { X obj->which_kind = SEE_INVISIBLE; X } X} X Xgr_weapon(obj, assign_wk) Xobject *obj; Xint assign_wk; X{ X short percent; X short i; X short blessing, increment; X X obj->what_is = WEAPON; X if (assign_wk) { X obj->which_kind = get_rand(0, (WEAPONS - 1)); X } X if ((obj->which_kind == ARROW) || (obj->which_kind == DAGGER) || X (obj->which_kind == SHURIKEN) | (obj->which_kind == DART)) { X obj->quantity = get_rand(3, 15); X obj->quiver = get_rand(0, 126); X } else { X obj->quantity = 1; X } X obj->hit_enchant = obj->d_enchant = 0; X X percent = get_rand(1, 96); X blessing = get_rand(1, 3); X X if (percent <= 16) { X increment = 1; X } else if (percent <= 32) { X increment = -1; X obj->is_cursed = 1; X } X if (percent <= 32) { X for (i = 0; i < blessing; i++) { X if (coin_toss()) { X obj->hit_enchant += increment; X } else { X obj->d_enchant += increment; X } X } X } X switch(obj->which_kind) { X case BOW: X case DART: X obj->damage = "1d1"; X break; X case ARROW: X obj->damage = "1d2"; X break; X case DAGGER: X obj->damage = "1d3"; X break; X case SHURIKEN: X obj->damage = "1d4"; X break; X case MACE: X obj->damage = "2d3"; X break; X case LONG_SWORD: X obj->damage = "3d4"; X break; X case TWO_HANDED_SWORD: X obj->damage = "4d5"; X break; X } X} X Xgr_armor(obj) Xobject *obj; X{ X short percent; X short blessing; X X obj->what_is = ARMOR; X obj->which_kind = get_rand(0, (ARMORS - 1)); X obj->class = obj->which_kind + 2; X if ((obj->which_kind == PLATE) || (obj->which_kind == SPLINT)) { X obj->class--; X } X obj->is_protected = 0; X obj->d_enchant = 0; X X percent = get_rand(1, 100); X blessing = get_rand(1, 3); X X if (percent <= 16) { X obj->is_cursed = 1; X obj->d_enchant -= blessing; X } else if (percent <= 33) { X obj->d_enchant += blessing; X } X} X Xgr_wand(obj) Xobject *obj; X{ X obj->what_is = WAND; X obj->which_kind = get_rand(0, (WANDS - 1)); X if (obj->which_kind == MAGIC_MISSILE) { X obj->class = get_rand(6, 12); X } else if (obj->which_kind == CANCELLATION) { X obj->class = get_rand(5, 9); X } else { X obj->class = get_rand(3, 6); X } X} X Xget_food(obj, force_ration) Xobject *obj; Xboolean force_ration; X{ X obj->what_is = FOOD; X X if (force_ration || rand_percent(80)) { X obj->which_kind = RATION; X } else { X obj->which_kind = FRUIT; X } X} X Xput_stairs() X{ X short row, col; X X gr_row_col(&row, &col, (FLOOR | TUNNEL)); X dungeon[row][col] |= STAIRS; X} X Xget_armor_class(obj) Xobject *obj; X{ X if (obj) { X return(obj->class + obj->d_enchant); X } X return(0); X} X Xobject * Xalloc_object() X{ X object *obj; X X if (free_list) { X obj = free_list; X free_list = free_list->next_object; X } else if (!(obj = (object *) md_malloc(sizeof(object)))) { X free_free_list(); X message("cannot allocate object, saving game", 0); X save_into_file(error_file); X } X obj->quantity = 1; X obj->ichar = 'L'; X obj->picked_up = obj->is_cursed = 0; X obj->in_use_flags = NOT_USED; X obj->identified = UNIDENTIFIED; X obj->damage = "1d1"; X return(obj); X} X Xfree_object(obj) Xobject *obj; X{ X obj->next_object = free_list; X free_list = obj; X} X Xmake_party() X{ X short n; X X party_room = gr_room(); X X n = rand_percent(99) ? party_objects(party_room) : 11; X if (rand_percent(99)) { X party_monsters(party_room, n); X } X} X Xshow_objects() X{ X object *obj; X short mc, rc, row, col; X object *monster; X X obj = level_objects.next_object; X X while (obj) { X row = obj->row; X col = obj->col; X X rc = get_mask_char(obj->what_is); X X if (dungeon[row][col] & MONSTER) { X if (monster = object_at(&level_monsters, row, col)) { X monster->trail_char = rc; X } X } X mc = mvinch(row, col); X if (((mc < 'A') || (mc > 'Z')) && X ((row != rogue.row) || (col != rogue.col))) { X mvaddch(row, col, rc); X } X obj = obj->next_object; X } X X monster = level_monsters.next_object; X X while (monster) { X if (monster->m_flags & IMITATES) { X mvaddch(monster->row, monster->col, (int) monster->disguise); X } X monster = monster->next_monster; X } X} X Xput_amulet() X{ X object *obj; X X obj = alloc_object(); X obj->what_is = AMULET; X rand_place(obj); X} X Xrand_place(obj) Xobject *obj; X{ X short row, col; X X gr_row_col(&row, &col, (FLOOR | TUNNEL)); X place_at(obj, row, col); X X} X Xnew_object_for_wizard() X{ X short ch, max, wk; X object *obj; X char buf[80]; X X if (pack_count((object *) 0) >= MAX_PACK_COUNT) { X message("pack full", 0); X return; X } X message("type of object?", 0); X X while (r_index("!?:)]=/,\033", (ch = rgetchar()), 0) == -1) { X sound_bell(); X } X check_message(); X X if (ch == '\033') { X return; X } X obj = alloc_object(); X X switch(ch) { X case '!': X obj->what_is = POTION; X max = POTIONS - 1; X break; X case '?': X obj->what_is = SCROLL; X max = SCROLLS - 1; X break; X case ',': X obj->what_is = AMULET; X break; X case ':': X get_food(obj, 0); X break; X case ')': X gr_weapon(obj, 0); X max = WEAPONS - 1; X break; X case ']': X gr_armor(obj); X max = ARMORS - 1; X break; X case '/': X gr_wand(obj); X max = WANDS - 1; X break; X case '=': X max = RINGS - 1; X obj->what_is = RING; X break; X } X if ((ch != ',') && (ch != ':')) { XGIL: X if (get_input_line("which kind?", "", buf, "", 0, 1)) { X wk = get_number(buf); X if ((wk >= 0) && (wk <= max)) { X obj->which_kind = (unsigned short) wk; X if (obj->what_is == RING) { X gr_ring(obj, 0); X } X } else { X sound_bell(); X goto GIL; X } X } else { X free_object(obj); X return; X } X } X get_desc(obj, buf); X message(buf, 0); X (void) add_to_pack(obj, &rogue.pack, 1); X} X Xnext_party() X{ X int n; X X n = cur_level; X while (n % PARTY_TIME) { X n++; X } X return(get_rand((n + 1), (n + PARTY_TIME))); X} END_OF_object.c if test 16345 -ne `wc -c <object.c`; then echo shar: \"object.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f throw.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"throw.c\" else echo shar: Extracting \"throw.c\" \(6032 characters\) sed "s/^X//" >throw.c <<'END_OF_throw.c' X/* X * throw.c X * X * This source herein may be modified and/or distributed by anybody who X * so desires, with the following restrictions: X * 1.) No portion of this notice shall be removed. X * 2.) Credit shall not be taken for the creation of this source. X * 3.) This code is not to be traded, sold, or used for personal X * gain or profit. X * X */ X X#ifndef CURSES X#include <curses.h> X#endif CURSES X#include "rogue.h" X Xextern short cur_room; Xextern char *curse_message; Xextern char hit_message[]; X Xthrow() X{ X short wch; X boolean first_miss = 1; X object *weapon; X short dir, row, col; X object *monster; X X while (!is_direction(dir = rgetchar())) { X sound_bell(); X if (first_miss) { X message("direction? ", 0); X first_miss = 0; X } X } X check_message(); X if (dir == CANCEL) { X return; X } X if ((wch = pack_letter("throw what?", WEAPON)) == CANCEL) { X return; X } X check_message(); X X if (!(weapon = get_letter_object(wch))) { X message("no such item.", 0); X return; X } X if ((weapon->in_use_flags & BEING_USED) && weapon->is_cursed) { X message(curse_message, 0); X return; X } X row = rogue.row; col = rogue.col; X X if ((weapon->in_use_flags & BEING_WIELDED) && (weapon->quantity <= 1)) { X unwield(rogue.weapon); X } else if (weapon->in_use_flags & BEING_WORN) { X mv_aquatars(); X unwear(rogue.armor); X print_stats(STAT_ARMOR); X } else if (weapon->in_use_flags & ON_EITHER_HAND) { X un_put_on(weapon); X } X monster = get_thrown_at_monster(weapon, dir, &row, &col); X mvaddch(rogue.row, rogue.col, rogue.fchar); X refresh(); X X if (rogue_can_see(row, col) && ((row != rogue.row) || (col != rogue.col))){ X mvaddch(row, col, get_dungeon_char(row, col)); X } X if (monster) { X wake_up(monster); X check_gold_seeker(monster); X X if (!throw_at_monster(monster, weapon)) { X flop_weapon(weapon, row, col); X } X } else { X flop_weapon(weapon, row, col); X } X vanish(weapon, 1, &rogue.pack); X} X Xthrow_at_monster(monster, weapon) Xobject *monster, *weapon; X{ X short damage, hit_chance; X short t; X X hit_chance = get_hit_chance(weapon); X damage = get_weapon_damage(weapon); X if ((weapon->which_kind == ARROW) && X (rogue.weapon && (rogue.weapon->which_kind == BOW))) { X damage += get_weapon_damage(rogue.weapon); X damage = ((damage * 2) / 3); X hit_chance += (hit_chance / 3); X } else if ((weapon->in_use_flags & BEING_WIELDED) && X ((weapon->which_kind == DAGGER) || X (weapon->which_kind == SHURIKEN) || X (weapon->which_kind == DART))) { X damage = ((damage * 3) / 2); X hit_chance += (hit_chance / 3); X } X t = weapon->quantity; X weapon->quantity = 1; X sprintf(hit_message, "the %s", name_of(weapon)); X weapon->quantity = t; X X if (!rand_percent(hit_chance)) { X (void) strcat(hit_message, "misses "); X return(0); X } X (void) strcat(hit_message, "hit "); X if ((weapon->what_is == WAND) && rand_percent(75)) { X zap_monster(monster, weapon->which_kind); X } else { X (void) mon_damage(monster, damage); X } X return(1); X} X Xobject * Xget_thrown_at_monster(obj, dir, row, col) Xobject *obj; Xshort dir; Xshort *row, *col; X{ X short orow, ocol; X short i, ch; X X orow = *row; ocol = *col; X X ch = get_mask_char(obj->what_is); X X for (i = 0; i < 24; i++) { X get_dir_rc(dir, row, col, 0); X if ((dungeon[*row][*col] == NOTHING) || X ((dungeon[*row][*col] & (HORWALL | VERTWALL | HIDDEN)) && X (!(dungeon[*row][*col] & TRAP)))) { X *row = orow; X *col = ocol; X return(0); X } X if ((i != 0) && rogue_can_see(orow, ocol)) { X mvaddch(orow, ocol, get_dungeon_char(orow, ocol)); X } X if (rogue_can_see(*row, *col)) { X if (!(dungeon[*row][*col] & MONSTER)) { X mvaddch(*row, *col, ch); X } X refresh(); X } X orow = *row; ocol = *col; X if (dungeon[*row][*col] & MONSTER) { X if (!imitating(*row, *col)) { X return(object_at(&level_monsters, *row, *col)); X } X } X if (dungeon[*row][*col] & TUNNEL) { X i += 2; X } X } X return(0); X} X Xflop_weapon(weapon, row, col) Xobject *weapon; Xshort row, col; X{ X object *new_weapon, *monster; X short i = 0; X char msg[80]; X boolean found = 0; X short mch, dch; X unsigned short mon; X X while ((i < 9) && dungeon[row][col] & ~(FLOOR | TUNNEL | DOOR | MONSTER)) { X rand_around(i++, &row, &col); X if ((row > (DROWS-2)) || (row < MIN_ROW) || X (col > (DCOLS-1)) || (col < 0) || (!dungeon[row][col]) || X (dungeon[row][col] & ~(FLOOR | TUNNEL | DOOR | MONSTER))) { X continue; X } X found = 1; X break; X } X X if (found || (i == 0)) { X new_weapon = alloc_object(); X *new_weapon = *weapon; X new_weapon->in_use_flags = NOT_USED; X new_weapon->quantity = 1; X new_weapon->ichar = 'L'; X place_at(new_weapon, row, col); X if (rogue_can_see(row, col) && X ((row != rogue.row) || (col != rogue.col))) { X mon = dungeon[row][col] & MONSTER; X dungeon[row][col] &= (~MONSTER); X dch = get_dungeon_char(row, col); X if (mon) { X mch = mvinch(row, col); X if (monster = object_at(&level_monsters, row, col)) { X monster->trail_char = dch; X } X if ((mch < 'A') || (mch > 'Z')) { X mvaddch(row, col, dch); X } X } else { X mvaddch(row, col, dch); X } X dungeon[row][col] |= mon; X } X } else { X short t; X X t = weapon->quantity; X weapon->quantity = 1; X sprintf(msg, "the %svanishes as it hits the ground", X name_of(weapon)); X weapon->quantity = t; X message(msg, 0); X } X} X Xrand_around(i, r, c) Xshort i, *r, *c; X{ X static char* pos = "\010\007\001\003\004\005\002\006\0"; X static short row, col; X short j; X X if (i == 0) { X short x, y, o, t; X X row = *r; X col = *c; X X o = get_rand(1, 8); X X for (j = 0; j < 5; j++) { X x = get_rand(0, 8); X y = (x + o) % 9; X t = pos[x]; X pos[x] = pos[y]; X pos[y] = t; X } X } X switch((short)pos[i]) { X case 0: X *r = row + 1; X *c = col + 1; X break; X case 1: X *r = row + 1; X *c = col - 1; X break; X case 2: X *r = row - 1; X *c = col + 1; X break; X case 3: X *r = row - 1; X *c = col - 1; X break; X case 4: X *r = row; X *c = col + 1; X break; X case 5: X *r = row + 1; X *c = col; X break; X case 6: X *r = row; X *c = col; X break; X case 7: X *r = row - 1; X *c = col; X break; X case 8: X *r = row; X *c = col - 1; X break; X } X} END_OF_throw.c if test 6032 -ne `wc -c <throw.c`; then echo shar: \"throw.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 2 \(of 5\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive&S&S&get_