rich@sdcsvax.UUCP (rich) (08/04/86)
This is an extended version of the public domain version of rogue. the game is slowly trying to look a bit like srogue. this version will only run on vms systems. hacking io.c to death should make it run on unix. like all public domain source do what you wish, just dont sell it . enjoy, rich #! /bin/sh ihnp4--\ decvax--\ akgua----\ dcdwest---\ somewhere--\ ucbvax-------- sdcsvax -- rich # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # doorcou.c # help.c # hit.c # init.c # inventor.c # io.c # level.c # This archive created: Mon Aug 4 11:41:18 1986 # By: rich ( lack of) export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'doorcou.c' then echo shar: "will not over-write existing file 'doorcou.c'" else cat << \SHAR_EOF > 'doorcou.c' #include "object.h" #include "monster.h" #include "room.h" #include "move.h" door_course(monster, entering, row, col) object *monster; short entering, row, col; { short trow, tcol, i, j, rn; short rrow, ccol; monster->row = row; monster->col = col; if (monster_can_see(monster, rogue.row, rogue.col)) { monster->trow = -1; return; } rn = get_room_number(row, col); if (entering) { /* entering room */ for (i = 0; i < MAXROOMS; i++) { if (!rooms[i].is_room || (i == rn)) continue; for (j = 0; j < 4; j++) { if (rooms[i].doors[j].other_room == rn) { monster->trow = rooms[i].doors[j].other_row; monster->tcol = rooms[i].doors[j].other_col; if ((monster->trow == row) && (monster->tcol == col)) { continue; } return; } } } } else { /* exiting room */ rrow = row; ccol = col; if (get_other_room(rn, &rrow, &ccol)) { monster->trow = rrow; monster->tcol = ccol; } else { monster->trow = -1; } } } get_other_room(rn, row, col) short rn, *row, *col; { short d = -1; if ((screen[*row][(*col)-1]&HORWALL)&&(screen[*row][(*col)+1]&HORWALL)){ if (screen[(*row)+1][*col] & FLOOR) { d = UP/2; } else { d = DOWN/2; } } else { if (screen[*row][(*col)+1] & FLOOR) { d = LEFT/2; } else { d = RIGHT/2; } } if ((d != -1) && (rooms[rn].doors[d].other_room > 0)) { *row = rooms[rn].doors[d].other_row; *col = rooms[rn].doors[d].other_col; return(1); } return(0); } SHAR_EOF fi if test -f 'help.c' then echo shar: "will not over-write existing file 'help.c'" else cat << \SHAR_EOF > 'help.c' help(what) int what;{ switch(what){ case '\003' : message(" quit",1); break; case '.' : message(" rest a turn",1); break; case 'i' : message(" inventory rogue pack",1); break; case 'f' : message(" fight",1); break; case 'F' : message(" fight harder",1); break; case 'h' : message(" move left",1); break; case 'j' : message(" move down",1); break; case 'k' : message(" move up",1); break; case 'l' : message(" move right",1); break; case 'y' : message(" move up and to the left",1); break; case 'u' : message(" move up and to the right",1); break; case 'n' : message(" move down and to the left",1); break; case 'b' : message(" move down and to the right",1); break; case 'H' : message(" run left",1); break; case 'J' : message(" run down",1); break; case 'K' : message(" run up",1); break; case 'L' : message(" run right",1); break; case 'Y' : message(" run up and to the left",1); break; case 'U' : message(" run up and to the right",1); break; case 'N' : message(" run down and to the left",1); break; case 'B' : message(" run down and to the right",1); break; case '\010' : message(" move left, until adjacent",1); break; case '\012' : message(" move down, until adjacent",1); break; case '\013' : message(" move up, until adjacent",1); break; case '\014' : message(" move right, until adjacent",1); break; case '\031' : message(" move up and to the left,until adjacent",1); break; case '\025' : message(" move up and to the right,until adjacent",1); break; case '\006' : message(" move down and to the left, until adjacent",1); break; case '\002' : message(" move down and to the right,until adjacent",1); break; case 'e' : message(" eat",1); break; case 'q' : message(" quaff potion",1); break; case 'r' : message(" read scroll",1); break; case 'm' : message(" move onto",1); break; case 'd' : message(" drop",1); break; case '\020' : message(" recall last message",1); break; case '>' : message(" go down stairs",1); break; case '<' : message(" go up stairs",1); break; case 'I' : message(" inventory a single item",1); break; case 'R' : message(" redaw screen",1); break; case 'T' : message(" take off armor",1); break; case 'W' : message(" put on armor",1); break; case 'P' : message(" put on armor",1); break; case 'w' : message(" wield",1); break; case 'c' : message(" call an item",1); break; case 'z' : message(" zap a wand",1); break; case 't' : message(" throw a weapon",1); break; case '\032' : message(" suspend process ",1); break; case '!' : message(" spawn a command",1); break; case 'v' : message(" version number",1); break; case 'Q' : message(" quit",1); break; case '/' : message(" identify monster",1); break; case '?' : message(" help on a command",1); break; default : message(" Unknown command",1); } } SHAR_EOF fi if test -f 'hit.c' then echo shar: "will not over-write existing file 'hit.c'" else cat << \SHAR_EOF > 'hit.c' #include <curses.h> #include "object.h" #include "move.h" #include "monster.h" object *fight_monster = 0; short detect_monster; char hit_message[80] = ""; extern short halluc, blind, being_held, interrupted; monster_hit(monster, other) register object *monster; char *other; { short damage, hit_chance; char *mn, *monster_name(); float minus; if (fight_monster && (monster != fight_monster)) { fight_monster = 0; } monster->trow = -1; hit_chance = monster->class; hit_chance -= (rogue.exp + rogue.exp); if (rogue.armor) hit_chance -= 3*(rogue.armor->damage_enchantment); if (hit_chance < 0) hit_chance = 0; if (!fight_monster) { interrupted = 1; } mn = monster_name(monster); if (!rand_percent(hit_chance)) { if (!fight_monster) { sprintf(hit_message + strlen(hit_message), "the %s misses", (other ? other : mn)); message(hit_message, 0); hit_message[0] = 0; } return; } if (!fight_monster) { sprintf(hit_message + strlen(hit_message), "the %s hit", (other ? other : mn)); message(hit_message, 0); hit_message[0] = 0; } if (monster->ichar != 'F') { damage = get_damage(monster->damage, 1); if (rogue.armor) minus = (float) (rogue.armor->class * 3.00 + rogue.armor->damage_enchantment); minus = minus/100.00 * (float) damage; damage -= (short) minus; } else { damage = monster->identified++; } if (damage > 0) { rogue_damage(damage, monster); } special_hit(monster); } rogue_hit(monster) register object *monster; { short damage, hit_chance; char mbuf[80], *monster_name(); float minus; short cx; if (check_xeroc(monster)) { return; } hit_chance = get_hit_chance(rogue.weapon); if (!rand_percent(hit_chance)) { if (!fight_monster) { strcpy(hit_message, "you miss "); } goto RET; } damage = get_weapon_damage(rogue.weapon); if (monster_damage(monster, damage)) { /* still alive? */ if (!fight_monster) { strcpy(hit_message, "you hit "); } } RET: check_orc(monster); wake_up(monster); } rogue_damage(d, monster) short d; object *monster; { extern char *player_name; static char byebye[80]; if (d >= rogue.hp_current) { rogue.hp_current = 0; print_stats(); killed_by(monster, 0); } rogue.hp_current -= d; print_stats(); if (rogue.hp_current < ((short)(rogue.hp_max*0.1+1))) { sprintf(byebye,"%s is about to die... ", player_name); message(byebye, 1); } } get_damage(ds, r) char *ds; { register short i = 0, j, n, d, total = 0; while (ds[i]) { n = get_number(ds+i); while (ds[i++] != 'd') ; d = get_number(ds+i); while ((ds[i] != '/') && ds[i]) i++; for (j = 0; j < n; j++) { if (r) { total += get_rand(1, d); } else { total += d; } } if (ds[i] == '/') { i++; } } return(total); } get_w_damage(obj) object *obj; { char new_damage[12]; register short to_hit, damage; register short i = 0; if (!obj) { return(-1); } to_hit = get_number(obj->damage) + obj->to_hit_enchantment; while (obj->damage[i++] != 'd') ; damage = get_number(obj->damage + i) + obj->damage_enchantment; sprintf(new_damage, "%dd%d", to_hit, damage); return(get_damage(new_damage, 1)); } get_number(s) register char *s; { register short i = 0; register short total = 0; while ((s[i] >= '0') && (s[i] <= '9')) { total = (10 * total) + (s[i] - '0'); i++; } return(total); } to_hit(obj) object *obj; { short tohit = 0; short i = 0; if (!obj) { return(1); } return(get_number(obj->damage) + obj->to_hit_enchantment); } damage_for_strength(s) { if (s <= 6) { return(s-5); } if (s <= 14) { return(1); } if (s <= 17) { return(3); } if (s <= 18) { return(4); } if (s <= 20) { return(5); } if (s <= 21) { return(6); } if (s <= 30) { return(7); } return(8); } monster_damage(monster, damage) object *monster; { char *mn, *monster_name(); short row, col; monster->quantity -= damage; if (monster->quantity <= 0) { row = monster->row; col = monster->col; remove_mask(row, col, MONSTER); mvaddch(row, col, get_room_char(screen[row][col])); refresh_vms(); fight_monster = 0; cough_up(monster); mn = monster_name(monster); sprintf(hit_message+strlen(hit_message), "defeated the %s", mn); message(hit_message, 1); hit_message[0] = 0; add_exp(monster->kill_exp); print_stats(); remove_from_pack(monster, &level_monsters); if (monster->ichar == 'F') { being_held = 0; } free(monster); return(0); } return(1); } fight(to_the_death) short to_the_death; { short ch; short row, col; short first_miss = 1; short possible_damage; object *object_at(); while (!is_direction(ch = getchartt())) { putchar(7); fflush(stdout); if (first_miss) { message("direction?", 0); first_miss = 0; } } check_message(); if (ch == CANCEL) { return; } row = rogue.row; col = rogue.col; get_dir_rc(ch, &row, &col); if (!(screen[row][col] & MONSTER) || blind || hiding_xeroc(row, col)) { NM: message("I see no monster there", 0); return; } fight_monster = object_at(&level_monsters, row, col); if ((fight_monster->m_flags & IS_INVIS) && !detect_monster) { goto NM; } possible_damage = ((get_damage(fight_monster->damage, 0) * 2) / 3); while (fight_monster) { single_move_rogue(ch, 0); if (!to_the_death && rogue.hp_current <= possible_damage) { fight_monster = 0; } if (!(screen[row][col] & MONSTER) || interrupted) { fight_monster = 0; } } } get_dir_rc(dir, row, col) short dir; short *row, *col; { switch(dir) { case 'h': if (*col > 0) { (*col)--; } break; case 'j': if (*row < (LINES-2)) { (*row)++; } break; case 'k': if (*row > MIN_ROW) { (*row)--; } break; case 'l': if (*col < (COLS-1)) { (*col)++; } break; case 'y': if ((*row > MIN_ROW) && (*col > 0)) { (*row)--; (*col)--; } break; case 'u': if ((*row > MIN_ROW) && (*col < (COLS-1))) { (*row)--; (*col)++; } break; case 'n': if ((*row < (LINES-2)) && (*col < (COLS-1))) { (*row)++; (*col)++; } break; case 'b': if ((*row < (LINES-2)) && (*col > 0)) { (*row)++; (*col)--; } break; } } get_hit_chance(weapon) object *weapon; { short hit_chance; hit_chance = 40; hit_chance += 3 * to_hit(weapon); hit_chance += (rogue.exp + rogue.exp); if (hit_chance > 100) hit_chance = 100; return(hit_chance); } get_weapon_damage(weapon) object *weapon; { short damage; damage = get_w_damage(weapon); damage += damage_for_strength(rogue.strength_current); damage += ((rogue.exp + 1) / 2); return(damage); } SHAR_EOF fi if test -f 'init.c' then echo shar: "will not over-write existing file 'init.c'" else cat << \SHAR_EOF > 'init.c' #include stdio.h #include curses.h #include "object.h" #include "room.h" char player[32]; char *player_name; short cant_int = 0, did_int = 0; extern char ichars[]; extern short party_room; extern short chan; extern short AMULET_LEVEL; init() { char *cuserid(); short i; int byebye(); if (!(player_name = cuserid(player))) { fprintf(stderr, "Hey! Who are you?"); ttclose(); exit(2); } /* * cheat for now */ printf("Hello %s, just a moment while I dig the dungeon...", player_name); fflush(stdout); /* lib$disable_ctrl(0x1000000, &old_mask); */ ttopen(); sleep(1); /* emulate Unix */ initscr(); for (i = 0; i < 26; i++) { ichars[i] = 0; } start_window(); if ((LINES < 24) || (COLS < 80)) { clean_up("must be played on 24 x 80 screen"); } LINES = SROWS; srand(time()); shuffle_colors(); mix_metals(); make_scroll_titles(); level_objects.next_object = 0; level_monsters.next_object = 0; player_init(); } player_init() { object *get_an_object(), *obj; rogue.pack.next_object = 0; obj = get_an_object(); get_food(obj); add_to_pack(obj, &rogue.pack, 1); obj = get_an_object(); /* initial armor */ get_rand_armor2(obj); obj->what_is = ARMOR; obj->identified = 1; add_to_pack(obj, &rogue.pack, 1); rogue.armor = obj; AMULET_LEVEL = get_rand(25,39) + obj->class; obj = get_an_object(); /* initial weapons */ obj->what_is = WEAPON; get_rand_weapon2(obj); obj->identified = 1; add_to_pack(obj, &rogue.pack, 1); rogue.weapon = obj; obj = get_an_object(); obj->what_is = WEAPON; obj->which_kind = SHORT_BOW; get_weapon_thd(obj); obj->is_cursed = 0; obj->damage = "1d8"; obj->to_hit_enchantment = 1; obj->damage_enchantment = 0; obj->identified = 1; add_to_pack(obj, &rogue.pack, 1); obj = get_an_object(); obj->what_is = WEAPON; obj->which_kind = ARROW; obj->quantity = get_rand(25, 35); get_weapon_thd(obj); obj->is_cursed = 0; obj->damage = "1d2"; obj->to_hit_enchantment = 0; obj->damage_enchantment = 0; obj->identified = 1; add_to_pack(obj, &rogue.pack, 1); } clean_up(estr) char *estr; { move(LINES-1, 0); refresh_vms(); stop_window(); printf("\n%s\n", estr); ttclose(); exit(1); } start_window() { crmode(); noecho(); nonl(); } stop_window() { endwin(); } byebye() { clean_up("Okay, bye bye!"); } SHAR_EOF fi if test -f 'inventor.c' then echo shar: "will not over-write existing file 'inventor.c'" else cat << \SHAR_EOF > 'inventor.c' #include curses.h #include "object.h" #include "macros.h" #include "move.h" char *metals[MAXMETALS] = { "steel ", "bronze ", "gold ", "silver ", "copper ", "nickel ", "cobalt ", "tin ", "iron ", "magnesium ", "chrome ", "carbon ", "platinum ", "silicon ", "titanium " }; char *syllables[MAXSYLLABLES] = { "blech ", "foo ", "barf ", "rech ", "bar ", "blech ", "quo ", "bloto ", "woh ", "caca ", "blorp ", "erp ", "festr ", "rot ", "slie ", "snorf ", "iky ", "yuky ", "ooze ", "ah ", "bahl ", "zep ", "druhl ", "flem ", "behil ", "arek ", "mep ", "zihr ", "grit ", "kona ", "kini ", "ichi ", "niah ", "ogr ", "ooh ", "ighr ", "coph ", "swerr ", "mihln ", "poxi " }; inventory(pack, mask) object *pack; unsigned short mask; { object *obj; short i = 0, j, maxlen = 0, n; char descriptions[MAX_PACK_COUNT+1][SCOLS]; short row, col; obj = pack->next_object; while (obj) { if (obj->what_is & mask) { descriptions[i][0] = ' '; descriptions[i][1] = obj->ichar; descriptions[i][2] = ')'; descriptions[i][3] = ' '; get_description(obj, descriptions[i]+4); if ((n = strlen(descriptions[i])) > maxlen) { maxlen = n; } i++; } obj = obj->next_object; } strcpy(descriptions[i++], " --press space to continue--"); if (maxlen < 27) maxlen = 27; col = COLS - (maxlen + 2); for (row = 0; ((row < i) && (row < SROWS)); row++) { if (row > 0) { for (j = col; j < COLS; j++) { descriptions[row-1][j-col] = mvinch(row, j); } descriptions[row-1][j-col] = 0; } mvaddstr(row, col, descriptions[row]); clrtoeol(); } refresh_vms(); wait_for_ack(0); move(0, 0); clrtoeol(); for (j = 1; j < i; j++) { mvaddstr(j, col, descriptions[j-1]); } } shuffle_colors() { short i, j, k; for (i = 0; i <= POTIONS; i++) { j = get_rand(0, (POTIONS - 1)); k = get_rand(0, (POTIONS - 1)); swap_string(id_potions[j].title, id_potions[k].title); } } make_scroll_titles() { short i, j, n; short sylls, s; for (i = 0; i < SCROLLS; i++) { sylls = get_rand(2, 5); strcpy(id_scrolls[i].title, "'"); for (j = 0; j < sylls; j++) { s = get_rand(1, (MAXSYLLABLES-1)); strcat(id_scrolls[i].title, syllables[s]); } n = strlen(id_scrolls[i].title); strcpy(id_scrolls[i].title+(n-1), "' "); } } get_description(obj, description) object *obj; char *description; { char *name_of(), *item_name; struct identify *id_table, *get_id_table(); char more_info[32]; if (obj->what_is == AMULET) { strcpy(description, "the amulet of Yendor "); return; } item_name = name_of(obj); if (obj->what_is == GOLD) { sprintf(description, "%d pieces of gold", obj->quantity); return; } if (obj->what_is != ARMOR) { if (obj->quantity == 1) { strcpy(description, "a "); } else { sprintf(description, "%d ", obj->quantity); } } if (obj->what_is == FOOD) { strcat(description, item_name); strcat(description, "of food "); return; } id_table = get_id_table(obj); if (obj->what_is & (WEAPON | ARMOR | WAND)) goto CHECK; switch(id_table[obj->which_kind].id_status) { case UNIDENTIFIED: CHECK: switch(obj->what_is) { case SCROLL: strcat(description, item_name); strcat(description, "entitled: "); strcat(description, id_table[obj->which_kind].title); break; case POTION: strcat(description, id_table[obj->which_kind].title); strcat(description, item_name); break; case WAND: if (obj->identified || (id_table[obj->which_kind].id_status == IDENTIFIED)) { goto ID; } if (id_table[obj->which_kind].id_status == CALLED) { goto CALL; } strcat(description, id_table[obj->which_kind].title); strcat(description, item_name); break; case ARMOR: if (obj->identified) { goto ID; } strcpy(description, id_table[obj->which_kind].title); break; case WEAPON: if (obj->identified) { goto ID; } strcat(description, name_of(obj)); if (obj == rogue.weapon) { strcat(description, "in hand"); } break; } break; case CALLED: CALL: switch(obj->what_is) { case SCROLL: case POTION: case WAND: strcat(description, item_name); strcat(description, "called "); strcat(description, id_table[obj->which_kind].title); goto MI; break; } break; case IDENTIFIED: ID: switch(obj->what_is) { case SCROLL: case POTION: strcat(description, item_name); strcat(description, id_table[obj->which_kind].real); break; case WAND: strcat(description, item_name); strcat(description, id_table[obj->which_kind].real); MI: if (obj->identified) { sprintf(more_info, "[%d]", obj->class); strcat(description, more_info); } break; case ARMOR: sprintf(description, "%s%d ", ((obj->damage_enchantment >= 0) ? "+" : ""), obj->damage_enchantment); strcat(description, id_table[obj->which_kind].title); sprintf(more_info, "[%d] ", get_armor_class(obj)); strcat(description, more_info); if (obj == rogue.armor) { strcat(description, "being worn"); } break; case WEAPON: sprintf(description+strlen(description), "%s%d,%s%d ", ((obj->to_hit_enchantment >= 0) ? "+" : ""), obj->to_hit_enchantment, ((obj->damage_enchantment >= 0) ? "+" : ""), obj->damage_enchantment); strcat(description, name_of(obj)); if (obj == rogue.weapon) { strcat(description, "in hand"); } break; } break; } } mix_metals() { short i, j, k; for (i = 0; i <= MAXMETALS; i++) { j = get_rand(0, MAXMETALS-1); k = get_rand(0, MAXMETALS-1); swap_string(metals[j], metals[k]); } for (i = 0; i < WANDS; i++) { strcpy(id_wands[i].title, metals[i]); } } single_inventory() { short ch; char description[SCOLS]; object *obj, *get_letter_object(); ch = get_pack_letter("inventory what? ", IS_OBJECT); if (ch == CANCEL) { return; } if (!(obj = get_letter_object(ch))) { message("No such item.", 0); return; } strcpy(description, "x) "); description[0] = ch; get_description(obj, description+3); message(description, 0); } struct identify *get_id_table(obj) object *obj; { switch(obj->what_is) { case SCROLL: return(id_scrolls); break; case POTION: return(id_potions); break; case WAND: return(id_wands); break; case WEAPON: return(id_weapons); break; case ARMOR: return(id_armors); break; } } SHAR_EOF fi if test -f 'io.c' then echo shar: "will not over-write existing file 'io.c'" else cat << \SHAR_EOF > 'io.c' /* Hi Rich. Here is the new io.c I told you about. Now every character is returned straight from the keyboard (except ^S and ^Q) so you don't need the interrupt catching routines. What you *do* need is to make sure that every exit from the program is covered by the ttclose() routine, otherwise you will end up in DCL without echo (you can just do a set term, but why?) Anyway, I am slowly (after work) making some progress in improving the game. First, I wanted to split up the modules more naturally to make future expansion easier (all potion effects in one module, all scroll effects in another, etc.). Anyway, pass any ideas along this way. BTW, this account will expire on 6/30/86 and will be replaced by 'donovan'. My *own* account is u557676751ea and will be up after 7/1. Good luck! - Mark Nagel ------------------------------- cut here ---------------------------------- */ #include stsdef.h #include ssdef.h #include descrip.h #include iodef.h #include ttdef.h #include tt2def.h #include jpidef.h #define NIBUF 128 /* Size of input buffer */ #define EFN 0 /* Event flag number */ char ibuf[NIBUF]; /* Input buffer */ int nibuf = 0; /* # of bytes in above */ int ibufi = 0; /* Read index */ int oldmode[3]; /* Old TTY mode bits */ int newmode[3]; /* New TTY mode bits */ short iochan; /* TTY I/O channel */ void ttopen() { struct dsc$descriptor idsc; struct dsc$descriptor odsc; char oname[40]; int iosb[2]; int status; odsc.dsc$a_pointer = "SYS$INPUT"; odsc.dsc$w_length = strlen(odsc.dsc$a_pointer); odsc.dsc$b_dtype = DSC$K_DTYPE_T; odsc.dsc$b_class = DSC$K_CLASS_S; idsc.dsc$b_dtype = DSC$K_DTYPE_T; idsc.dsc$b_class = DSC$K_CLASS_S; do { idsc.dsc$a_pointer = odsc.dsc$a_pointer; idsc.dsc$w_length = odsc.dsc$w_length; odsc.dsc$a_pointer = &oname[0]; odsc.dsc$w_length = sizeof(oname); status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc); if (status != SS$_NORMAL && status != SS$_NOTRAN) exit(status); if (oname[0] == 0x1B) { odsc.dsc$a_pointer += 4; odsc.dsc$w_length -= 4; } } while (status == SS$_NORMAL); status = SYS$ASSIGN(&odsc, &iochan, 0, 0); if (status != SS$_NORMAL) exit(status); status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0, oldmode, sizeof(oldmode), 0, 0, 0, 0); if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) exit(status); newmode[0] = oldmode[0]; /* Only in version 4. */ newmode[1] = oldmode[1] | TT$M_NOECHO | TT$M_TTSYNC; newmode[2] = oldmode[2] | TT2$M_PASTHRU; status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, newmode, sizeof(newmode), 0, 0, 0, 0); if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) exit(status); } char getchartt() { int status; int iosb[2]; int term[2]; term[0] = 0; term[1] = 0; while (ibufi >= nibuf) { ibufi = 0; status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED, iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0); if (status != SS$_NORMAL) continue; status = iosb[0] & 0xFFFF; if (status != SS$_NORMAL && status != SS$_TIMEOUT) continue; nibuf = (iosb[0]>>16) + (iosb[1]>>16); if (nibuf == 0) { status = SYS$QIOW(EFN, iochan, IO$_READLBLK, iosb, 0, 0, ibuf, 1, 0, term, 0, 0); if (status != SS$_NORMAL) continue; if ((iosb[0]&0xFFFF) != SS$_NORMAL) continue; nibuf = (iosb[0]>>16) + (iosb[1]>>16); } } if (ibuf[ibufi] == '\r') ibuf[ibufi] = '\n'; return (ibuf[ibufi++]); } void ttclose() { int status; int iosb[1]; status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, oldmode, sizeof(oldmode), 0, 0, 0, 0); if (status != SS$_NORMAL || (iosb[0]&0xFFFF) != SS$_NORMAL) exit(status); status = SYS$DASSGN(iochan); if (status != SS$_NORMAL) exit(status); } spawn_command(command) char *command; { struct dsc$descriptor descr_command; /* * make the character strings */ char the_command[40]; if((!strcmp("sh",command)) || command[0]=='!' || command[0]=='\0'){ lib$spawn(0,0,0,0,0,0,0,0,0,0,0,0); return; } sprintf(the_command,"%s",command); /* * Give descriptors the number of printable ascii * characters */ descr_command.dsc$w_length=strlen(the_command); /* * Give descriptors the addresses of the strings */ descr_command.dsc$a_pointer=the_command; /* * Define the string descriptor class */ descr_command.dsc$b_class=DSC$K_CLASS_S; /* * Explain that it is an ascii string. */ descr_command.dsc$b_dtype=DSC$K_DTYPE_T; lib$spawn(&descr_command,0,0,0,0,0,0,0,0,0,0,0); } /* * this is here because vms curses sucks. * the curser was following hidden monsters about. */ #include curses refresh_vms() { static int old_x,old_y; static int odd=0; getyx(stdscr,old_y,old_x); move(LINES -2,COLS-1); if (odd == 0){ odd = 1; addch(' '); } else { odd = 0; addch('.'); } refresh(); move(old_y,old_x); } SHAR_EOF fi if test -f 'level.c' then echo shar: "will not over-write existing file 'level.c'" else cat << \SHAR_EOF > 'level.c' #include curses.h #include "move.h" #include "object.h" #include "room.h" #include "macros.h" short current_level = 0, max_level = 1; extern short AMULET_LEVEL; extern short current_room; char *hunger_str = ""; short party_room; extern short being_held; extern short detect_monster, has_amulet; int level_points[] = { 10, 20, 40, 80, 160, 320, 640, 1300, 2600, 5200, 10000, 20000, 40000, 80000, 160000, 320000, 1000000, 10000000 }; make_level() { short i; short must_exist1, must_exist2; party_room = -1; if (current_level < 126) { current_level++; } if (current_level > max_level) max_level = current_level; if (rand_percent(50)) { must_exist1 = 1; must_exist2 = 7; } else { must_exist1 = 3; must_exist2 = 5; } for (i = 0; i < MAXROOMS; i++) { make_room(i, must_exist1, must_exist2, 4); } try_rooms(0, 1, 2); try_rooms(0, 3, 6); try_rooms(2, 5, 8); try_rooms(6, 7, 8); for (i = 0; i < (MAXROOMS); i++) { connect_rooms(i, i+1, must_exist1, must_exist2, 4); if (i < (MAXROOMS-3)) { connect_rooms(i, i+3, must_exist1, must_exist2, 4); } } add_dead_ends(); if (!has_amulet && (current_level >= AMULET_LEVEL)) { put_amulet(); } } make_room(n, r1, r2, r3) { short left_col, right_col, top_row, bottom_row; short width, height; short row_offset, col_offset; short i, j; short ch; switch(n) { case 0: left_col = 0; right_col = COL1-1; top_row = MIN_ROW; bottom_row = ROW1-1; break; case 1: left_col = COL1+1; right_col = COL2-1; top_row = MIN_ROW; bottom_row = ROW1-1; break; case 2: left_col = COL2+1; right_col = COLS-1; top_row = MIN_ROW; bottom_row = ROW1-1; break; case 3: left_col = 0; right_col = COL1-1; top_row = ROW1+1; bottom_row = ROW2-1; break; case 4: left_col = COL1+1; right_col = COL2-1; top_row = ROW1+1; bottom_row = ROW2-1; break; case 5: left_col = COL2+1; right_col = COLS-1; top_row = ROW1+1; bottom_row = ROW2-1; break; case 6: left_col = 0; right_col = COL1-1; top_row = ROW2+1; bottom_row = LINES - 2; break; case 7: left_col = COL1+1; right_col = COL2-1; top_row = ROW2+1; bottom_row = LINES - 2; break; case 8: left_col = COL2+1; right_col = COLS-1; top_row = ROW2+1; bottom_row = LINES - 2; break; } if ((n != r1) && (n != r2) && (n != r3) && rand_percent(45)) { goto END; } height = get_rand(4, (bottom_row-top_row+1)); width = get_rand(7, (right_col-left_col-2)); row_offset = get_rand(0, ((bottom_row-top_row)-height+1)); col_offset = get_rand(0, ((right_col-left_col)-width+1)); top_row += row_offset; bottom_row = top_row + height - 1; left_col += col_offset; right_col = left_col + width - 1; rooms[n].is_room = 1; for (i = top_row; i <= bottom_row; i++) { for (j = left_col; j <= right_col; j++) { if ((i == top_row) || (i == bottom_row)) { ch = HORWALL; } else if (((i != top_row) && (i != bottom_row)) && ((j == left_col) || (j == right_col))) { ch = VERTWALL; } else { ch = FLOOR; } add_mask(i, j, ch); } } END: rooms[n].top_row = top_row; rooms[n].bottom_row = bottom_row; rooms[n].left_col = left_col; rooms[n].right_col = right_col; rooms[n].height = height; rooms[n].width = width; } connect_rooms(room1, room2, m1, m2, m3) { if ((room1 != m1) && (room1 != m2) && (room1 != m3) && (room2 != m1) && (room2 != m2) && (room2 != m3)) { if (rand_percent(80)) { return; } } if (adjascent(room1, room2)) { do_connect(room1, room2); } } do_connect(room1, room2) { short row1, col1, row2, col2, dir; if ((rooms[room1].left_col > rooms[room2].right_col) && (on_same_row(room1, room2))) { put_door(room1, LEFT, &row1, &col1); put_door(room2, RIGHT, &row2, &col2); dir = LEFT; } else if ((rooms[room2].left_col > rooms[room1].right_col) && (on_same_row(room1, room2))) { put_door(room1, RIGHT, &row1, &col1); put_door(room2, LEFT, &row2, &col2); dir = RIGHT; } else if ((rooms[room1].top_row > rooms[room2].bottom_row) && (on_same_col(room1, room2))) { put_door(room1, UP, &row1, &col1); put_door(room2, DOWN, &row2, &col2); dir = UP; } else if ((rooms[room2].top_row > rooms[room1].bottom_row) && (on_same_col(room1, room2))) { put_door(room1, DOWN, &row1, &col1); put_door(room2, UP, &row2, &col2); dir = DOWN; } else { return; } draw_simple_passage(row1, col1, row2, col2, dir); if (rand_percent(10)) { draw_simple_passage(row1, col1, row2, col2, dir); } rooms[room1].doors[dir/2].other_room = room2; rooms[room1].doors[dir/2].other_row = row2; rooms[room1].doors[dir/2].other_col = col2; rooms[room2].doors[(((dir+4)%8)/2)].other_room = room1; rooms[room2].doors[(((dir+4)%8)/2)].other_row = row1; rooms[room2].doors[(((dir+4)%8)/2)].other_col = col1; } clear_level() { int i, j; for (i = 0; i < MAXROOMS; i++) { rooms[i].is_room = 0; for (j = 0; j < 4; j++) { rooms[i].doors[j].other_room = NO_ROOM; } } for (i = 0; i < SROWS; i++) { for (j = 0; j < SCOLS; j++) { screen[i][j] = BLANK; } } detect_monster = 0; being_held = 0; } print_stats() { char mbuf[100]; sprintf(mbuf, "Level: %d Gold: %3d Hp: %2d(%d) Str: %2d(%d) Arm: %2d Exp: %d/%d %s", current_level, rogue.gold, rogue.hp_current, rogue.hp_max, rogue.strength_current, rogue.strength_max, get_armor_class(rogue.armor), rogue.exp, rogue.exp_points, hunger_str); mvaddstr(LINES-1, 0, mbuf); clrtoeol(); refresh_vms(); } add_mask(row, col, mask) int row, col; unsigned short mask; { if (mask == DOOR) { remove_mask(row, col, HORWALL); remove_mask(row, col, VERTWALL); } screen[row][col] |= mask; /*switch(mask) { case FLOOR: mvaddch(row, col, '.'); break; case STAIRS: mvaddch(row, col, '%'); break; case DOOR: mvaddch(row, col, '+'); break; case VERTWALL: mvaddch(row, col, '|'); break; case HORWALL: mvaddch(row, col, '-'); break; case TUNNEL: mvaddch(row, col, '#'); break; }*/ } remove_mask(row, col, mask) { screen[row][col] &= (~mask); } adjascent(room1, room2) { if ((!rooms[room1].is_room) || (!rooms[room2].is_room)) { return(0); } two_sort(room1, room2); return((on_same_col(room1,room2) || on_same_row(room1, room2)) && (((room2 - room1) == 1) || (((room2 - room1) == 3)))); } put_door(rn, dir, row, col) short *row, *col; { switch(dir) { case UP: case DOWN: *row = ((dir == UP) ? rooms[rn].top_row : rooms[rn].bottom_row); *col = get_rand(rooms[rn].left_col+1, rooms[rn].right_col-1); break; case RIGHT: case LEFT: *row = get_rand(rooms[rn].top_row+1, rooms[rn].bottom_row-1); *col = (dir == LEFT) ? rooms[rn].left_col : rooms[rn].right_col; break; } add_mask(*row, *col, DOOR); } draw_simple_passage(row1, col1, row2, col2, dir) { short i, middle; if ((dir == LEFT) || (dir == RIGHT)) { if (col2 < col1) { swap(row1, row2); swap(col1, col2); } middle = get_rand(col1+1, col2-1); for (i = col1+1; i != middle; i++) { add_mask(row1, i, TUNNEL); } for (i = row1; i != row2; i += (row1 > row2) ? -1 : 1) { add_mask(i, middle, TUNNEL); } for (i = middle; i != col2; i++) { add_mask(row2, i, TUNNEL); } } else { if (row2 < row1) { swap(row1, row2); swap(col1, col2); } middle = get_rand(row1+1, row2-1); for (i = row1+1; i != middle; i++) { add_mask(i, col1, TUNNEL); } for (i = col1; i != col2; i += (col1 > col2) ? -1 : 1) { add_mask(middle, i, TUNNEL); } for (i = middle; i != row2; i++) { add_mask(i, col2, TUNNEL); } } } on_same_row(room1, room2) { return((room1 / 3) == (room2 / 3)); } on_same_col(room1, room2) { return((room1 % 3) == (room2 % 3)); } add_dead_ends() { short i, j; short start; short row, col, distance, dir; short found; short dead_end_percent; if (current_level <= 2) return; start = get_rand(0, (MAXROOMS-1)); dead_end_percent = 12 + current_level + current_level; for (i = 0; i < MAXROOMS; i++) { j = ((start + i) % MAXROOMS); if (rooms[j].is_room) continue; if (!rand_percent(dead_end_percent)) continue; row = rooms[j].top_row + get_rand(0, 6); col = rooms[j].left_col + get_rand(0, 19); found = 0; while (!found) { distance = get_rand(8, 20); dir = get_rand(0, 3) * 2; for (j = 0; (j < distance) && !found; j++) { switch(dir) { case UP: if ((row - 1) >= MIN_ROW) { --row; } break; case RIGHT: if ((col + 1) < (COLS-1)) { ++col; } break; case DOWN: if ((row + 1) < (LINES-2)) { ++row; } break; case LEFT: if ((col - 1) > 0) { --col; } break; } if ((screen[row][col] & VERTWALL) || (screen[row][col] & HORWALL) || (screen[row][col] & DOOR)) { break_in(row, col, screen[row][col], dir); found = 1; } else { add_mask(row, col, TUNNEL); } } } } } break_in(row, col, ch, dir) { short rn; short i, drow, dcol; if (ch == DOOR) { return; } rn = get_room_number(row, col); if (ch == VERTWALL) { if (col == rooms[rn].left_col) { if (rooms[rn].doors[LEFT/2].other_room != NO_ROOM) { drow = door_row(rn, LEFT); for (i = row; i != drow; i += (drow < row) ? -1 : 1) { add_mask(i, col-1, TUNNEL); } } else { rooms[rn].doors[LEFT/2].other_room = DEAD_END; add_mask(row, col, DOOR); } } else { if (rooms[rn].doors[RIGHT/2].other_room != NO_ROOM) { drow = door_row(rn, RIGHT); for (i = row; i != drow; i += (drow < row) ? -1 : 1) { add_mask(i, col+1, TUNNEL); } } else { rooms[rn].doors[RIGHT/2].other_room = DEAD_END; add_mask(row, col, DOOR); } } } else { /* break in througt top or bottom --- */ if (col == rooms[rn].left_col) { if (row == MIN_ROW) { add_mask(row+1, col-1, TUNNEL); break_in(row+1, col, VERTWALL, RIGHT); } else if (row == (LINES-2)) { add_mask(row-1, col-1, TUNNEL); break_in(row-1, col, VERTWALL, RIGHT); } else { if (row == rooms[rn].top_row) { if (dir == RIGHT) { add_mask(row-1, col-1, TUNNEL); add_mask(row-1, col, TUNNEL); } add_mask(row-1, col+1, TUNNEL); break_in(row, col+1, HORWALL, DOWN); } else { if (dir == RIGHT) { add_mask(row+1, col-1, TUNNEL); add_mask(row+1, col, TUNNEL); } add_mask(row+1, col+1, TUNNEL); break_in(row, col+1, HORWALL, UP); } } return; } else if (col == rooms[rn].right_col) { if (row == MIN_ROW) { add_mask(row+1, col+1, TUNNEL); break_in(row+1, col, VERTWALL, LEFT); } else if (row == (LINES-2)) { add_mask(row-1, col+1, TUNNEL); break_in(row-1, col, VERTWALL, LEFT); } else { if (row == rooms[rn].top_row) { if (dir == DOWN) { add_mask(row-1, col+1, TUNNEL); add_mask(row, col+1, TUNNEL); } add_mask(row+1, col+1, TUNNEL); break_in(row+1, col, VERTWALL, LEFT); } else { if (dir == UP) { add_mask(row+1, col+1, TUNNEL); add_mask(row, col+1, TUNNEL); } add_mask(row-1, col+1, TUNNEL); break_in(row-1, col, VERTWALL, LEFT); } } return; } if (row == rooms[rn].top_row) { if (rooms[rn].doors[UP/2].other_room != NO_ROOM) { dcol = door_col(rn, UP); for (i = col; i != dcol; i += (dcol < col) ? -1 : 1) { add_mask(row-1, i, TUNNEL); } } else { rooms[rn].doors[UP/2].other_room = DEAD_END; add_mask(row, col, DOOR); } } else { if (rooms[rn].doors[DOWN/2].other_room != NO_ROOM) { dcol = door_col(rn, DOWN); for (i = col; i != dcol; i += (dcol < col) ? -1 : 1) { add_mask(row+1, i, TUNNEL); } } else { rooms[rn].doors[DOWN/2].other_room = DEAD_END; add_mask(row, col, DOOR); } } } return(0); } door_row(rn, dir) { short i, col, row; if (rooms[rn].doors[dir/2].other_room == NO_ROOM) { return(-1); } row = rooms[rn].top_row; switch(dir) { case LEFT: col = rooms[rn].left_col; for (i = row; !(screen[i][col] & DOOR); i++) ; break; case RIGHT: col = rooms[rn].right_col; for (i = row; !(screen[i][col] & DOOR); i++) ; break; } return(i); } door_col(rn, dir) { short i, col, row; if (rooms[rn].doors[dir/2].other_room == NO_ROOM) { return(-1); } col = rooms[rn].left_col; switch(dir) { case UP: row = rooms[rn].top_row; for (i = col; !(screen[row][i] & DOOR); i++) ; break; case DOWN: row = rooms[rn].bottom_row; for (i = col; !(screen[row][i] & DOOR); i++) ; break; } return(i); } put_player() { for (;;) { get_rand_row_col(&rogue.row, &rogue.col, (FLOOR | IS_OBJECT)); current_room = get_room_number(rogue.row, rogue.col); if (current_room != party_room) { break; } } } check_down() { if (screen[rogue.row][rogue.col] & STAIRS) { return(1); } message("I see no way down", 0); return(0); } check_up() { if (!(screen[rogue.row][rogue.col] & STAIRS)) { message("I see no way up", 0); return(0); } if (!has_amulet) { message("your way is magically blocked", 0); return(0); } if (current_level == 1) { win(); } else { current_level -= 2; return(1); } } add_exp(e) { char mbuf[40]; short new_exp; short i, hp; if (rogue.exp_points < MAX_EP) { rogue.exp_points += e; if (rogue.exp_points >= level_points[rogue.exp-1]) { new_exp = get_exp_level(rogue.exp_points); for (i = rogue.exp+1; i <= new_exp; i++) { sprintf(mbuf, "welcome to level %d", i); message(mbuf, 0); hp = get_rand(3, 10); rogue.hp_current += hp; rogue.hp_max += hp; print_stats(); } rogue.exp = new_exp; } } if (rogue.exp_points > MAX_EP) rogue.exp_points = MAX_EP; print_stats(); } get_exp_level(e) { short i; for (i = 0; i < 50; i++) { if (level_points[i] > e) { break; } } return(i+1); } try_rooms(r1, r2, r3) { if (rooms[r1].is_room && !rooms[r2].is_room && rooms[r3].is_room) { if (rand_percent(75)) { do_connect(r1, r3); } } } SHAR_EOF fi exit 0 # End of shell archive -- ihnp4--\ decvax--\ akgua----\ dcdwest---\ somewhere--\ ucbvax-------- sdcsvax -- rich