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_