Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 (Tek) 9/28/84 based on 9/17/84; site zeus.UUCP Path: utzoo!watmath!clyde!burl!ulysses!gamma!epsilon!zeta!sabre!petrus!bellcore!decvax!decwrl!pyramid!hplabs!tektronix!teklds!zeus!tims From: tims@zeus.UUCP (Tim Stoehr) Newsgroups: net.sources.games Subject: Re: rogue 5.3 clone source, shell archiv Message-ID: <25@zeus.UUCP> Date: Wed, 5-Mar-86 13:26:26 EST Article-I.D.: zeus.25 Posted: Wed Mar 5 13:26:26 1986 Date-Received: Sat, 8-Mar-86 21:35:36 EST References: <6@zeus.UUCP> <24600002@orstcs.UUCP> Organization: Tektronix, Beaverton OR Lines: 3034 > Would it be possible to re-post the last half of the ROGUE5.3 clone? Many > sites, including this one, are using the Notes system to peruse netnews. Notes > trucates individual postings to a maximum 64K. So the following files were > missing from the ROGUE posting: > > object.c, pack.c, play.c random.c, room.c, score.c, special_hit.c, > throw.c, use.c, zap.c > > Thank you. OK, here are the named files in a shell archive of about 59K bytes. #!/bin/sh-----cut here-----cut here-----cut here-----cut here----- # shar: Shell Archiver # Run the following text with /bin/sh to create: # object.c # pack.c # play.c # random.c # room.c # score.c # special_hit.c # throw.c # use.c # zap.c cat - << \SHAR_EOF > object.c #include #include "object.h" #include "room.h" object level_objects; unsigned short screen[SROWS][SCOLS]; extern short current_level, max_level; extern short party_room; short has_amulet = 0; short foods = 0; fighter rogue = { 0, 0, /* armor, weapon */ 12, 12, /* Hp */ 16, 16, /* Str */ {0}, /* pack */ 0, /* gold */ 1, 0, /* exp, exp_points */ 0, 0, /* row, col */ '@', /* char */ 1200 /* moves */ }; struct identify id_potions[POTIONS] = { {100, "blue \0 ", "of increase strength ",0}, {250, "red \0 ", "of restore strength ",0}, {100, "green \0 ", "of healing ",0}, {200, "grey \0 ", "of extra healing ",0}, {10, "brown \0 ", "of poison ",0}, {300, "clear \0 ", "of raise level ",0}, {10, "pink \0 ", "of blindness ",0}, {25, "white \0 ", "of hallucination ",0}, {100, "purple \0 ", "of detect monster ",0}, {100, "black \0 ", "of detect things ",0}, {10, "yellow \0 ", "of confusion ",0} }; struct identify id_scrolls[SCROLLS] = { {505, " ", "of protect armor ", 0}, {200, " ", "of hold monster ", 0}, {235, " ", "of enchant weapon ", 0}, {235, " ", "of enchant armor ", 0}, {175, " ", "of identify ", 0}, {190, " ", "of teleportation ", 0}, {25, " ", "of sleep ", 0}, {610, " ", "of scare monster ", 0}, {210, " ", "of remove curse ", 0}, {100, " ", "of create monster ",0}, {25, " ", "of aggravate monster ",0} }; struct identify id_weapons[WEAPONS] = { {150, "short bow ", "", 0}, {15, "arrows ", "", 0}, {35, "shurikens ", "", 0}, {370, "mace ", "", 0}, {480, "long sword ", "", 0}, {590, "two-handed sword ", "", 0} }; struct identify id_armors[ARMORS] = { {300, "leather armor ", "", (UNIDENTIFIED)}, {300, "ring mail ", "", (UNIDENTIFIED)}, {400, "scale mail ", "", (UNIDENTIFIED)}, {500, "chain mail ", "", (UNIDENTIFIED)}, {600, "banded mail ", "", (UNIDENTIFIED)}, {600, "splint mail ", "", (UNIDENTIFIED)}, {700, "plate mail ", "", (UNIDENTIFIED)} }; struct identify id_wands[WANDS] = { {25, " ", "of teleport away ",0}, {50, " ", "of slow monster ", 0}, {45, " ", "of kill monster ",0}, {8, " ", "of invisibility ",0}, {55, " ", "of polymorph ",0}, {2, " ", "of haste monster ",0}, {25, " ", "of put to sleep ",0}, {0, " ", "of do nothing ",0} }; put_objects() { short row, col, i, n; char *malloc(); object *obj, *get_rand_object(); if (current_level < max_level) return; n = get_rand(2, 4); if (rand_percent(35)) n++; if (rand_percent(50)) { strcpy(id_weapons[SHURIKEN].title, "daggers "); } if (rand_percent(5)) { make_party(); } for (i = 0; i < n; i++) { obj = get_rand_object(); put_object_rand_location(obj); add_to_pack(obj, &level_objects, 0); } put_gold(); } put_gold() { short i, j; short row,col; object *obj, *get_an_object(); for (i = 0; i < MAXROOMS; i++) { if (rooms[i].is_room && rand_percent(GOLD_PERCENT)) { for (j = 0; j < 25; j++) { row = get_rand(rooms[i].top_row+1, rooms[i].bottom_row-1); col = get_rand(rooms[i].left_col+1, rooms[i].right_col-1); if ((screen[row][col] == FLOOR) || (screen[row][col] == PASSAGE)) { put_gold_at(row, col); break; } } continue; } } } put_gold_at(row, col) { object *obj; obj = get_an_object(); obj->row = row; obj->col = col; obj->what_is = GOLD; obj->quantity = get_rand((2*current_level), (16*current_level)); add_mask(row, col, GOLD); add_to_pack(obj, &level_objects, 0); } put_object_at(obj, row, col) object *obj; { obj->row = row; obj->col = col; add_mask(row, col, obj->what_is); add_to_pack(obj, &level_objects, 0); } object *object_at(pack, row, col) object *pack; { object *obj; obj = pack->next_object; while (obj && (obj->row != row) || (obj->col != col)) { obj = obj->next_object; } return(obj); } object *get_letter_object(ch) { object *obj; obj = rogue.pack.next_object; while (obj && (obj->ichar != ch)) { obj = obj->next_object; } return(obj); } free_stuff(objlist) object *objlist; { object *obj; while (objlist->next_object) { obj = objlist->next_object; objlist->next_object = objlist->next_object->next_object; free(obj); } } char *name_of(obj) object *obj; { char *retstring; switch(obj->what_is) { case SCROLL: retstring = obj->quantity > 1 ? "scrolls " : "scroll "; break; case POTION: retstring = obj->quantity > 1 ? "potions " : "potion "; break; case FOOD: retstring = obj->quantity > 1 ? "rations " : "ration "; break; case WAND: retstring = "wand "; break; case WEAPON: switch(obj->which_kind) { case ARROW: retstring=obj->quantity > 1 ? "arrows " : "arrow "; break; case SHURIKEN: if (id_weapons[SHURIKEN].title[0] == 'd') { retstring=obj->quantity > 1 ? "daggers " : "dagger "; } else { retstring=obj->quantity > 1?"shurikens ":"shuriken "; } break; default: retstring = id_weapons[obj->which_kind].title; } break; default: retstring = "unknown "; break; } return(retstring); } object *get_rand_object() { object *obj, *get_an_object(); obj = get_an_object(); if (foods < (current_level/2)) { obj->what_is = FOOD; } else { obj->what_is = get_rand_what_is(); } obj->identified = 0; switch(obj->what_is) { case SCROLL: get_rand_scroll(obj); break; case POTION: get_rand_potion(obj); break; case WEAPON: get_rand_weapon(obj); break; case ARMOR: get_rand_armor(obj); break; case WAND: get_rand_wand(obj); break; case FOOD: foods++; get_food(obj); break; } return(obj); } get_rand_what_is() { short percent; short what_is; percent = get_rand(1, 92); if (percent <= 30) { what_is = SCROLL; } else if (percent <= 60) { what_is = POTION; } else if (percent <= 65) { what_is = WAND; } else if (percent <= 75) { what_is = WEAPON; } else if (percent <= 85) { what_is = ARMOR; } else { what_is = FOOD; } return(what_is); } get_rand_scroll(obj) object *obj; { short percent; percent = get_rand(0, 82); if (percent <= 5) { obj->which_kind = PROTECT_ARMOR; } else if (percent <= 11) { obj->which_kind = HOLD_MONSTER; } else if (percent <= 20) { obj->which_kind = CREATE_MONSTER; } else if (percent <= 35) { obj->which_kind = IDENTIFY; } else if (percent <= 43) { obj->which_kind = TELEPORT; } else if (percent <= 52) { obj->which_kind = SLEEP; } else if (percent <= 57) { obj->which_kind = SCARE_MONSTER; } else if (percent <= 66) { obj->which_kind = REMOVE_CURSE; } else if (percent <= 71) { obj->which_kind = ENCHANT_ARMOR; } else if (percent <= 76) { obj->which_kind = ENCHANT_WEAPON; } else { obj->which_kind = AGGRAVATE_MONSTER; } } get_rand_potion(obj) object *obj; { short percent; percent = get_rand(1, 105); if (percent <= 5) { obj->which_kind = RAISE_LEVEL; } else if (percent <= 15) { obj->which_kind = DETECT_OBJECTS; } else if (percent <= 25) { obj->which_kind = DETECT_MONSTER; } else if (percent <= 35) { obj->which_kind = INCREASE_STRENGTH; } else if (percent <= 45) { obj->which_kind = RESTORE_STRENGTH; } else if (percent <= 55) { obj->which_kind = HEALING; } else if (percent <= 65) { obj->which_kind = EXTRA_HEALING; } else if (percent <= 75) { obj->which_kind = BLINDNESS; } else if (percent <= 85) { obj->which_kind = HALLUCINATION; } else if (percent <= 95) { obj->which_kind = CONFUSION; } else { obj->which_kind = POISON; } } get_rand_weapon(obj) object *obj; { short percent; short i; short blessing, cursed, increment; obj->which_kind = get_rand(0, (WEAPONS-1)); if ((obj->which_kind == ARROW) || (obj->which_kind == SHURIKEN)) { obj->quantity = get_rand(3, 15); obj->quiver = get_rand(0, 126); } else { obj->quantity = 1; } obj->identified = 0; obj->to_hit_enchantment = obj->damage_enchantment = 0; get_weapon_thd(obj); /* notice, long swords are ALWAYS cursed or blessed */ percent = get_rand(1, ((obj->which_kind == LONG_SWORD) ? 32 : 96)); blessing = get_rand(1, 3); obj->is_cursed = 0; if (percent <= 16) { increment = 1; } else if (percent <= 32) { increment = -1; obj->is_cursed = 1; } if (percent <= 32) { for (i = 0; i < blessing; i++) { if (rand_percent(50)) { obj->to_hit_enchantment += increment; } else { obj->damage_enchantment += increment; } } } switch(obj->which_kind) { case BOW: obj->damage = "1d2"; break; case ARROW: obj->damage = "1d2"; break; case SHURIKEN: obj->damage = "1d4"; break; case MACE: obj->damage = "2d3"; break; case LONG_SWORD: obj->damage = "3d4"; break; case TWO_HANDED_SWORD: obj->damage = "4d5"; break; } } get_rand_armor(obj) object *obj; { short percent; short blessing; obj->which_kind = get_rand(0, (ARMORS-1)); obj->class = obj->which_kind + 2; if ((obj->which_kind == PLATE) || (obj->which_kind == SPLINT)) { obj->class--; } obj->is_cursed = 0; obj->is_protected = 0; obj->damage_enchantment = 0; percent = get_rand(1, 100); blessing = get_rand(1, 3); if (percent <= 16) { obj->is_cursed = 1; obj->damage_enchantment -= blessing; } else if (percent <= 33) { obj->damage_enchantment += blessing; } } get_rand_wand(obj) object *obj; { obj->which_kind = get_rand(0, (WANDS-1)); obj->class = get_rand(3, 7); } get_food(obj) object *obj; { obj->which_kind = obj->what_is = FOOD; } put_stairs() { short row, col; get_rand_row_col(&row, &col, (FLOOR | TUNNEL)); screen[row][col] = STAIRS; } get_weapon_thd(obj) object *obj; { switch(obj->which_kind) { case BOW: break; case ARROW: break; case SHURIKEN: break; case MACE: break; case LONG_SWORD: break; case TWO_HANDED_SWORD: break; } } get_armor_class(obj) object *obj; { if (obj) { return(obj->class + obj->damage_enchantment); } return(0); } object *get_an_object() { object *obj; char *malloc(); if (!(obj = (object *) malloc(sizeof(object)))) { clean_up("Cannot allocate item"); } obj->quantity = 1; obj->ichar = 'L'; obj->picked_up = 0; /* not picked up yet */ return(obj); } make_party() { object *obj; short n; party_room = get_rand_room(); n = fill_room_with_objects(party_room); fill_room_with_monsters(party_room, n); } show_objects() { object *obj; obj = level_objects.next_object; while (obj) { mvaddch(obj->row, obj->col, get_room_char(obj->what_is)); obj = obj->next_object; } } put_amulet() { short row, col; object *obj, *get_an_object(); obj = get_an_object(); obj->what_is = AMULET; put_object_rand_location(obj); add_to_pack(obj, &level_objects, 0); } put_object_rand_location(obj) object *obj; { short row, col; get_rand_row_col(&row, &col, (FLOOR | TUNNEL)); add_mask(row, col, obj->what_is); obj->row = row; obj->col = col; } SHAR_EOF cat - << \SHAR_EOF > pack.c #include #include "move.h" #include "object.h" char *CURSE_MESSAGE = "you can't, it appears to be cursed"; char ichars[26]; extern short has_amulet; object *add_to_pack(obj, pack, condense) object *obj, *pack; { object *op, *check_duplicate(); if (condense) { if (op = check_duplicate(obj, pack)) { free(obj); return(op); } else { obj->ichar = next_avail_ichar(); } } if (pack->next_object == 0) { pack->next_object = obj; } else { op = pack->next_object; while (op->next_object) { op = op->next_object; } op->next_object = obj; } obj->next_object = 0; return(obj); } remove_from_pack(obj, pack) object *obj, *pack; { while (pack->next_object != obj) { pack = pack->next_object; } pack->next_object = pack->next_object->next_object; } object *pick_up(row, col, status) short *status; { object *obj, *object_at(), *add_to_pack(); obj = object_at(&level_objects, row, col); *status = 1; if ((obj->what_is == SCROLL) && (obj->which_kind == SCARE_MONSTER) && (obj->picked_up > 0)) { message("the scroll turns to dust as you pick it up", 1); remove_from_pack(obj, &level_objects); remove_mask(row, col, SCROLL); free(obj); *status = 0; if (id_scrolls[SCARE_MONSTER].id_status == UNIDENTIFIED) { id_scrolls[SCARE_MONSTER].id_status = IDENTIFIED; } return(0); } if (obj->what_is == GOLD) { rogue.gold += obj->quantity; remove_mask(row, col, GOLD); remove_from_pack(obj, &level_objects); print_stats(); return(obj); /* obj will be free()ed in single_move() */ } if (get_pack_count(obj) >= MAX_PACK_COUNT) { message("Pack too full", 1); return(0); } if (obj->what_is == AMULET) { has_amulet = 1; } remove_mask(row, col, obj->what_is); remove_from_pack(obj, &level_objects); obj = add_to_pack(obj, &rogue.pack, 1); obj->picked_up++; return(obj); } drop() { object *obj, *get_letter_object(), *new; short ch; object *get_an_object(); char description[SCOLS]; if (screen[rogue.row][rogue.col] & IS_OBJECT) { message("There's already something there", 0); return; } if (!rogue.pack.next_object) { message("You have nothing to drop", 0); return; } ch = get_pack_letter("drop what? ", IS_OBJECT); if (ch == CANCEL) { return; } if (!(obj = get_letter_object(ch))) { message("No such item.", 0); return; } if (obj == rogue.weapon) { if (obj->is_cursed) { message(CURSE_MESSAGE, 0); return; } rogue.weapon = 0; } else if (obj == rogue.armor) { if (obj->is_cursed) { message(CURSE_MESSAGE, 0); return; } rogue.armor = 0; print_stats(); } obj->row = rogue.row; obj->col = rogue.col; if ((obj->quantity > 1) && (obj->what_is != WEAPON)) { obj->quantity--; new = get_an_object(); *new = *obj; new->quantity = 1; obj = new; goto ADD; } if (obj->what_is == AMULET) { has_amulet = 0; } make_avail_ichar(obj->ichar); remove_from_pack(obj, &rogue.pack); ADD: add_to_pack(obj, &level_objects, 0); add_mask(rogue.row, rogue.col, obj->what_is); strcpy(description, "dropped "); get_description(obj, description+8); message(description, 0); register_move(); } object *check_duplicate(obj, pack) object *obj, *pack; { object *op; if (!(obj->what_is & (WEAPON | FOOD | SCROLL | POTION))) { return(0); } op = pack->next_object; while (op) { if ((op->what_is == obj->what_is) && (op->which_kind == obj->which_kind)) { if ((obj->what_is != WEAPON) || ((obj->what_is == WEAPON) && ((obj->which_kind == ARROW) || (obj->which_kind == SHURIKEN)) && (obj->quiver == op->quiver))) { op->quantity += obj->quantity; return(op); } } op = op->next_object; } return(0); } next_avail_ichar() { short i; for (i = 'a'; i < 'z'; i++) { if (!ichars[i-'a']) { ichars[i-'a'] = 1; return(i); } } return(0); } make_avail_ichar(ch) { ichars[ch - 'a'] = 0; } wait_for_ack(prompt) { if (prompt) { printf("%s ", MORE); fflush(stdout); } while (getchar() != ' ') ; } get_pack_letter(prompt, mask) char *prompt; unsigned short mask; { short first_miss = 1; short ch; while (!is_pack_letter(ch = getchar())) { putchar(7); fflush(stdout); if (first_miss) { WHICH: message(prompt, 0); first_miss = 0; } } if (ch == LIST) { check_message(); inventory(&rogue.pack, mask); goto WHICH; } check_message(); return(ch); } take_off() { char description[SCOLS]; object *obj; if (rogue.armor) { if (rogue.armor->is_cursed) { message(CURSE_MESSAGE, 0); } else { mv_aquatars(); obj = rogue.armor; rogue.armor = 0; strcpy(description, "was wearing "); get_description(obj, description+12); message(description, 0); print_stats(); register_move(); } } else { message("not wearing any", 0); } } wear() { short ch; register object *obj; char description[SCOLS]; if (rogue.armor) { message("your already wearing some", 0); return; } ch = get_pack_letter("wear what? ", ARMOR); if (ch == CANCEL) { return; } if (!(obj = get_letter_object(ch))) { message("No such item.", 0); return; } if (obj->what_is != ARMOR) { message("You can't wear that", 0); return; } rogue.armor = obj; obj->identified = 1; get_description(obj, description); message(description, 0); print_stats(); register_move(); } wield() { short ch; register object *obj; char description[SCOLS]; if (rogue.weapon && rogue.weapon->is_cursed) { message(CURSE_MESSAGE, 0); return; } ch = get_pack_letter("wield what? ", WEAPON); if (ch == CANCEL) { return; } if (!(obj = get_letter_object(ch))) { message("No such item.", 0); return; } if (obj->what_is != WEAPON) { message("You can't wield that", 0); return; } if (obj == rogue.weapon) { message("in use", 0); } else { rogue.weapon = obj; get_description(obj, description); message(description, 0); register_move(); } } call_it() { short ch; register object *obj; struct identify *id_table, *get_id_table(); char buf[MAX_TITLE_LENGTH+2]; ch = get_pack_letter("call what? ", (SCROLL | POTION | WAND)); if (ch == CANCEL) { return; } if (!(obj = get_letter_object(ch))) { message("No such item.", 0); return; } if (!(obj->what_is & (SCROLL | POTION | WAND))) { message("surely you already know what that's called", 0); return; } id_table = get_id_table(obj); if (get_input_line(buf, id_table[obj->which_kind].title)) { id_table[obj->which_kind].id_status = CALLED; strcpy(id_table[obj->which_kind].title, buf); } } get_pack_count(new_obj) object *new_obj; { object *obj; short count = 0; if (!(obj = rogue.pack.next_object)) { return(0); } while (obj) { if (obj->what_is != WEAPON) { count += obj->quantity; } else { if ((new_obj->what_is != WEAPON) || ((obj->which_kind != ARROW) && (obj->which_kind != SHURIKEN)) || (new_obj->which_kind != obj->which_kind) || (obj->quiver != new_obj->quiver)) { count++; } } obj = obj->next_object; } return(count); } SHAR_EOF cat - << \SHAR_EOF > play.c #include #include "object.h" #include "move.h" short interrupted = 0; extern short party_room, detect_monster; extern char hit_message[]; play_level() { short ch; int count = 0; for (;;) { interrupted = 0; if (hit_message[0]) { message(hit_message); hit_message[0] = 0; } move(rogue.row, rogue.col); refresh(); ch = getchar(); check_message(); CH: switch(ch) { case '.': rest((count > 0) ? count : 1); break; case 'i': inventory(&rogue.pack, IS_OBJECT); break; /*case 'p': inventory(&level_objects, IS_OBJECT); break;*/ case 'f': fight(0); break; case 'F': fight(1); break; case 'h': case 'j': case 'k': case 'l': case 'y': case 'u': case 'n': case 'b': single_move_rogue(ch, 1); break; case 'H': case 'J': case 'K': case 'L': case 'B': case 'Y': case 'U': case 'N': case '\010': case '\012': case '\013': case '\014': case '\031': case '\025': case '\016': case '\002': multiple_move_rogue(ch); break; case 'e': eat(); break; case 'q': quaff(); break; case 'r': read_scroll(); break; case 'm': move_onto(); break; case 'd': drop(); break; case '\020': remessage(); break; case '>': if (check_down()) { return; } break; case '<': if (check_up()) { return; } break; case 'I': single_inventory(); break; case '\022': wrefresh(curscr); break; case 'T': take_off(); break; case 'W': case 'P': wear(); break; case 'w': wield(); break; case 'c': call_it(); break; case 'z': zapp(); break; case 't': throw(); break; case '\032': tstp(); break; case '!': shell(); break; case 'v': message("i_rogue: Version 1.0. (stoehr was here)", 0); break; case 'Q': quit(); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': count = 0; do { count = (10 * count) + (ch - '0'); ch = getchar(); } while ((ch >= '0') && (ch <= '9')); goto CH; break; case ' ': break; default: message("unknown command"); break; } } } SHAR_EOF cat - << \SHAR_EOF > random.c #include "macros.h" get_rand(x, y) int x, y; { long r, random(); int s; two_sort(x, y); r = random(); r = (r % ((y-x)+1)) + x; s = (int) r; return(s); } rand_percent(percentage) { return(get_rand(1, 100) <= percentage); } SHAR_EOF cat - << \SHAR_EOF > room.c #include #include "room.h" #include "object.h" #include "move.h" short current_room; room rooms[MAXROOMS]; extern short detect_monster; extern short blind; light_up_room() { short i, j; if (blind) return; for (i = rooms[current_room].top_row; i <= rooms[current_room].bottom_row; i++) { for (j = rooms[current_room].left_col; j <= rooms[current_room].right_col; j++) { mvaddch(i, j, get_room_char(screen[i][j], i, j)); } } mvaddch(rogue.row, rogue.col, rogue.fchar); } light_passage(row, col) { short i, j, i_end, j_end; if (blind) return; i_end = (row < (LINES-2)) ? 1 : 0; j_end = (col < (COLS-1)) ? 1 : 0; for (i = ((row > MIN_ROW) ? -1 : 0); i <= i_end; i++) { for (j = ((col > 0) ? -1 : 0); j <= j_end; j++) { if (is_passable(row+i, col+j)) { mvaddch(row+i, col+j, get_room_char(screen[row+i][col+j], row+i, col+j)); } } } } darken_room(rn) short rn; { short i, j; if (blind) return; for (i = rooms[rn].top_row + 1; i < rooms[rn].bottom_row; i++) { for (j = rooms[rn].left_col + 1; j < rooms[rn].right_col; j++) { if (!is_object(i, j) && !(detect_monster && (screen[i][j] & MONSTER))) { if (!hiding_xeroc(i, j)) { mvaddch(i, j, ' '); } } } } } get_room_char(mask, row, col) register short mask; register short row, col; { if (mask & MONSTER) { return(get_monster_char_row_col(row, col)); } if (mask & SCROLL) { return('?'); } if (mask & POTION) { return('!'); } if (mask & FOOD) { return(':'); } if (mask & WAND) { return('/'); } if (mask & ARMOR) { return(']'); } if (mask & WEAPON) { return(')'); } if (mask & GOLD) { return('*'); } if (mask & TUNNEL) { return('#'); } if (mask & HORWALL) { return('-'); } if (mask & VERTWALL) { return('|'); } if (mask & AMULET) { return(','); } if (mask & FLOOR) { return('.'); } if (mask & DOOR) { return('+'); } if (mask & STAIRS) { return('%'); } return(' '); } get_rand_row_col(row, col, mask) short *row, *col; unsigned short mask; { short rn; AGAIN: do { *row = get_rand(MIN_ROW, SROWS-2); *col = get_rand(0, SCOLS-1); rn = get_room_number(*row, *col); } while (!(screen[*row][*col] & mask) || (rn == NO_ROOM)); if (screen[*row][*col] & (~mask)) goto AGAIN; } get_rand_room() { short i; do { i = get_rand(0, MAXROOMS-1); } while (!rooms[i].is_room); return(i); } fill_room_with_objects(rn) { short i; object *obj, *get_rand_object(); short n, N, row, col; N = ((rooms[rn].bottom_row - rooms[rn].top_row) - 1) * ((rooms[rn].right_col - rooms[rn].left_col) - 1); n = get_rand(5, 10); if (n > N) n = N - 2; for (i = 0; i < n; i++) { do { row = get_rand(rooms[rn].top_row+1, rooms[rn].bottom_row-1); col = get_rand(rooms[rn].left_col+1, rooms[rn].right_col-1); } while (screen[row][col] != FLOOR); obj = get_rand_object(); put_object_at(obj, row, col); } return(n); } get_room_number(row, col) { short i; for (i = 0; i < MAXROOMS; i++) { if ((row >= rooms[i].top_row)&&(row <= rooms[i].bottom_row) && (col >= rooms[i].left_col)&&(col <= rooms[i].right_col)) { return(i); } } return(NO_ROOM); } shell() { char *getenv(), *rindex(); char *sh; int status; move(LINES-1, 0); refresh(); stop_window(); putchar('\n'); if (!(sh = getenv("SHELL"))) { sh = "/bin/sh"; } if (!fork()) { if (setreuid(-1, getuid()) < 0) exit(1); execl(sh, rindex(sh, '/') + 1, 0); exit(0); } wait(&status); start_window(); wrefresh(curscr); } SHAR_EOF cat - << \SHAR_EOF > score.c #include #include #include "object.h" #include "monster.h" #include "room.h" #include extern char *player_name; extern char *monster_names[]; extern short has_amulet, max_level; killed_by(monster, other) object *monster; short other; { char buf[80]; short i; signal(SIGINT, SIG_IGN); if (other != QUIT) { rogue.gold = ((rogue.gold * 9) / 10); } if (other) { switch(other) { case HYPOTHERMIA: strcpy(buf, "died of hypothermia"); break; case STARVATION: strcpy(buf, "died of starvation"); break; case QUIT: strcpy(buf, "quit"); break; } } else { strcpy(buf, "Killed by "); if (is_vowel(monster_names[monster->ichar - 'A'])) { strcat(buf, "an "); } else { strcat(buf, "a "); } strcat(buf, monster_names[monster->ichar - 'A']); } strcat(buf, " with "); sprintf(buf+strlen(buf), "%d gold", rogue.gold); message(buf, 0); message(""); score(monster, other); } win() { rogue.armor = 0; /* disarm and relax */ rogue.weapon = 0; clear(); mvaddstr(10, 11, "@ @ @@@ @ @ @ @ @ @@@ @ @ @"); mvaddstr(11, 11, " @ @ @ @ @ @ @ @ @ @ @ @@ @ @"); mvaddstr(12, 11, " @ @ @ @ @ @ @ @ @ @ @ @ @ @"); mvaddstr(13, 11, " @ @ @ @ @ @ @ @ @ @ @ @@"); mvaddstr(14, 11, " @ @@@ @@@ @@ @@ @@@ @ @ @"); mvaddstr(17, 11, "Congratulations, you have been admitted to the"); mvaddstr(18, 11, "Fighter's Guild. You return home, sell all your"); mvaddstr(19, 11, "treasures at great profit and retire into comfort."); message(""); message(""); id_all(); sell_pack(); score((object *) 0, WIN); } quit() { message("really quit?", 1); if (getchar() != 'y') { check_message(); return; } check_message(); killed_by(0, QUIT); } score(monster, other) object *monster; { int fd; while (access(SCOREFILE, W_OK) || access(SCOREFILE, R_OK)) { umask(0); if ((fd = creat(SCOREFILE, 0666)) < 0) { message("cannot find/read/write score file"); message(SCOREFILE); message("I'll wait, you go off and try to fix it"); message("hit space when finished fixing the problem"); wait_for_ack(0); } else { close(fd); } } put_scores(monster, other); } put_scores(monster, other) object *monster; { short i, j, n, rank = 10, x, dont_insert = 0; char scores[10][82]; int fd, s; fd = open(SCOREFILE, O_RDWR, 0); for (i = 0; i < 10; i++) { L: if (((n = read(fd, scores[i], 80)) < 80) && (n != 0)) { message("error in score file format"); message(""); clean_up("sorry, score file is out of order"); } else if (n == 0) { break; } if (!ncmp(scores[i]+16, player_name)) { x = 7; while (scores[i][x] == ' ') x++; s = get_number(scores[i] + x); if (s <= rogue.gold) { goto L; } else { dont_insert = 1; } } } if (dont_insert) goto DI; for (j = 0; j < i; j++) { if (rank > 9) { x = 7; while (scores[j][x] == ' ') x++; s = get_number(scores[j] + x); if (s <= rogue.gold) { rank = j; } } } if (i == 0) { rank = 0; } else if ((i < 10) && (rank > 9)) { rank = i; } if (rank <= 9) { insert_score(scores, rank, i, monster, other); if (i < 10) { i++; } } lseek(fd, 0, 0); DI: clear(); mvaddstr(3, 30, "Top Ten Rogueists"); mvaddstr(8, 0, "Rank\tScore\tName"); signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); for (j = 0; j < i; j++) { if (j == rank) { standout(); } if (j == 9) { scores[j][0] = '1'; scores[j][1] = '0'; } else { scores[j][0] = ' '; scores[j][1] = j + '1'; } mvaddstr(j+10, 0, scores[j]); if (rank < 10) { write(fd, scores[j], 80); } if (j == rank) { standend(); } } refresh(); close(fd); clean_up(""); } insert_score(scores, rank, n, monster, other) char scores[][82]; short rank, n; object *monster; { short i, k; char buf[82]; for (i = (n - 1); i >= rank; i--) { if (i < 9) { strcpy(scores[i+1], scores[i]); } } sprintf(buf, "%2d %5d %s: ", rank+1, rogue.gold, player_name); if (other) { switch(other) { case HYPOTHERMIA: strcat(buf, "died of hypothermia"); break; case STARVATION: strcat(buf, "died of starvation"); break; case QUIT: strcat(buf, "quit"); break; case WIN: strcat(buf, "a total winner"); break; } } else { strcat(buf, "killed by "); if (is_vowel(monster_names[monster->ichar - 'A'])) { strcat(buf, "an "); } else { strcat(buf, "a "); } strcat(buf, monster_names[monster->ichar - 'A']); } sprintf(buf+strlen(buf), " on level %d ", max_level); if ((other != WIN) && has_amulet) { strcat(buf, "with amulet"); } for (i = strlen(buf); i < 79; i++) { buf[i] = ' '; } buf[79] = 0; strcpy(scores[rank], buf); } is_vowel(ch) short ch; { return( (ch == 'a') || (ch == 'e') || (ch == 'i') || (ch == 'o') || (ch == 'u') ); } sell_pack() { object *obj; short row = 2, val; char buf[80]; obj = rogue.pack.next_object; clear(); while (obj) { mvaddstr(1, 0, "Value Item"); if (obj->what_is == FOOD) { goto NEXT; } obj->identified = 1; val = get_value(obj); rogue.gold += val; if (row < SROWS) { sprintf(buf, "%5d ", val); get_description(obj, buf+11); mvaddstr(row++, 0, buf); } NEXT: obj = obj->next_object; } refresh(); message(""); } get_value(obj) object *obj; { short wc; int val; wc = obj->which_kind; switch(obj->what_is) { case WEAPON: val = id_weapons[wc].value; if ((wc == ARROW) || (wc == SHURIKEN)) { val *= obj->quantity; } val += (obj->damage_enchantment * 85); val += (obj->to_hit_enchantment * 85); break; case ARMOR: val = id_armors[wc].value; val += (obj->damage_enchantment * 75); if (obj->is_protected) { val += 200; } break; case WAND: val = id_wands[wc].value * obj->class; break; case SCROLL: val = id_scrolls[wc].value * obj->quantity; break; case POTION: val = id_potions[wc].value * obj->quantity; break; case AMULET: val = 5000; break; } if (val <= 0) { val = 10; } return(val); } id_all() { short i; for (i = 0; i < SCROLLS; i++) { id_scrolls[i].id_status = IDENTIFIED; } for (i = 0; i < WEAPONS; i++) { id_weapons[i].id_status = IDENTIFIED; } for (i = 0; i < ARMORS; i++) { id_armors[i].id_status = IDENTIFIED; } for (i = 0; i < WANDS; i++) { id_wands[i].id_status = IDENTIFIED; } for (i = 0; i < POTIONS; i++) { id_potions[i].id_status = IDENTIFIED; } } ncmp(s1, s2) char *s1, *s2; { short i = 0; int r; while(s1[i] != ':') i++; s1[i] = 0; r = strcmp(s1, s2); s1[i] = ':'; return(r); } SHAR_EOF cat - << \SHAR_EOF > special_hit.c #include #include "object.h" #include "move.h" #include "monster.h" short being_held; extern short current_level, max_level, has_amulet, detect_monster; extern int level_points[]; special_hit(monster) object *monster; { switch(monster->ichar) { case 'A': rust(monster); break; case 'F': being_held = 1; break; case 'I': freeze(monster); break; case 'L': steal_gold(monster); break; case 'N': steal_item(monster); break; case 'R': sting(monster); break; case 'V': drain_life(); break; case 'W': drain_level(); break; } } rust(monster) object *monster; { if (!rogue.armor || (get_armor_class(rogue.armor) <= 1) || (rogue.armor->which_kind == LEATHER)) { return; } if (rogue.armor->is_protected) { if (!monster->identified) { message("the rust vanishes instantly", 0); monster->identified = 1; } } else { rogue.armor->damage_enchantment--; message("your armor weakens", 0); print_stats(); } } freeze(monster) object *monster; { short freeze_percent = 99; short i, n; if (rand_percent(12)) return; freeze_percent -= (rogue.strength_current+(rogue.strength_current/2)); freeze_percent -= rogue.exp * 4; freeze_percent -= (get_armor_class(rogue.armor) * 5); freeze_percent -= (rogue.hp_max / 3); if (freeze_percent > 10) { monster->identified = 1; message("you are frozen", 1); n = get_rand(5, 9); for (i = 0; i < n; i++) { move_monsters(); } if (rand_percent(freeze_percent)) { for (i = 0; i < 50; i++) { move_monsters(); } killed_by((object *)0, HYPOTHERMIA); } message("you can move again", 1); monster->identified = 0; } } steal_gold(monster) object *monster; { int amount; if (rand_percent(15)) return; if (rogue.gold > 50) { amount = rogue.gold > 1000 ? get_rand(8, 15) : get_rand(2, 5); amount = rogue.gold / amount; } else { amount = rogue.gold/2; } amount += (get_rand(0, 2) - 1) * (rogue.exp + current_level); if ((amount <= 0) && (rogue.gold > 0)) { amount = rogue.gold; } if (amount > 0) { rogue.gold -= amount; message("your purse feels lighter", 0); print_stats(); } disappear(monster); } steal_item(monster) object *monster; { object *obj; short i, n, has_something = 0; char description[80]; if (rand_percent(15)) return; obj = rogue.pack.next_object; if (!obj) { goto DSPR; } while (obj) { if ((obj != rogue.armor) && (obj != rogue.weapon)) { has_something = 1; break; } obj = obj->next_object; } if (!has_something) goto DSPR; n = get_rand(0, MAX_PACK_COUNT); obj = rogue.pack.next_object; for (i = 0; i <= n; i++) { obj = obj->next_object; while (!obj || (obj == rogue.weapon) || (obj == rogue.armor)) { if (!obj) { obj = rogue.pack.next_object; } else { obj = obj->next_object; } } } strcpy(description, "she stole "); get_description(obj, description+10); message(description, 0); if (obj->what_is == AMULET) { has_amulet = 0; } vanish(obj, 0); DSPR: disappear(monster); } disappear(monster) object *monster; { short row, col; row = monster->row; col = monster->col; remove_mask(row, col, MONSTER); if (can_see(row, col)) { mvaddch(row, col, get_room_char(screen[row][col], row, col)); } remove_from_pack(monster, &level_monsters); free(monster); } cough_up(monster) object *monster; { object *obj, *get_an_object(),*get_rand_object(); short row, col, i, j, n; if (current_level < max_level) { return; } switch(monster->ichar) { case 'L': obj = get_an_object(); obj->what_is = GOLD; obj->quantity = get_rand(9, 599); break; default: if (rand_percent(monster->which_kind)) { obj = get_rand_object(); break; } return; } row = monster->row; col = monster->col; for (n = 0; n <= 5; n++) { for (i = -n; i <= n; i++) { if (try_to_cough(row+n, col+i, obj)) { return; } if (try_to_cough(row-n, col+i, obj)) { return; } } for (i = -n; i <= n; i++) { if (try_to_cough(row+i, col-n, obj)) { return; } if (try_to_cough(row+i, col+n, obj)) { return; } } } free(obj); } try_to_cough(row, col, obj) short row, col; object *obj; { if ((row(LINES-2))||(col<0)||(col>(COLS-1))) { return(0); } if ((!(screen[row][col] & IS_OBJECT)) && (screen[row][col] & (TUNNEL|FLOOR|DOOR)) && !(screen[row][col] & MONSTER)) { put_object_at(obj, row, col); mvaddch(row, col, get_room_char(screen[row][col], row, col)); refresh(); return(1); } return(0); } orc_gold(monster) object *monster; { short i, j, row, col, rn, s; if (monster->identified) { return(0); } if ((rn = get_room_number(monster->row, monster->col)) < 0) { return(0); } for (i = rooms[rn].top_row+1; i < rooms[rn].bottom_row; i++) { for (j = rooms[rn].left_col+1; j < rooms[rn].right_col; j++) { if ((screen[i][j] & GOLD) && !(screen[i][j] & MONSTER)) { monster->m_flags |= CAN_GO; s = monster_can_go(monster, i, j); monster->m_flags &= (~CAN_GO); if (s) { move_monster_to(monster, i, j); monster->m_flags |= IS_ASLEEP; monster->m_flags &= (~WAKENS); monster->identified = 1; return(1); } monster->identified = 1; monster->m_flags |= CAN_GO; mv_monster(monster, i, j); monster->m_flags &= (~CAN_GO); monster->identified = 0; return(1); } } } return(0); } check_orc(monster) object *monster; { if (monster->ichar == 'O') { monster->identified = 1; } } check_xeroc(monster) object *monster; { char *monster_name(); char msg[80]; if ((monster->ichar == 'X') && monster->identified) { wake_up(monster); monster->identified = 0; mvaddch(monster->row, monster->col, get_room_char(screen[monster->row][monster->col], monster->row, monster->col)); check_message(); sprintf(msg, "wait, that's a %s!", monster_name(monster)); message(msg, 1); return(1); } return(0); } hiding_xeroc(row, col) register short row, col; { object *object_at(), *monster; if ((current_level < XEROC1) || (current_level > XEROC2) || !(screen[row][col] & MONSTER)) { return(0); } monster = object_at(&level_monsters, row, col); if ((monster->ichar == 'X') && monster->identified) { return(1); } return(0); } sting(monster) object *monster; { short ac, sting_chance = 35; char msg[80], *monster_name(); if (rogue.strength_current < 5) return; ac = get_armor_class(rogue.armor); sting_chance += (6 * (6 - ac)); if (rogue.exp > 8) { sting_chance -= (6 * (rogue.exp - 8)); } if (sting_chance > 100) { sting_chance = 100; } else if (sting_chance <= 0) { sting_chance = 1; } if (rand_percent(sting_chance)) { sprintf(msg, "the %s's bite has weakened you", monster_name(monster)); message(msg, 0); rogue.strength_current--; print_stats(); } } drain_level() { if (!rand_percent(20) || (rogue.exp <= 7)) { return; } rogue.exp_points = level_points[rogue.exp-2] - get_rand(10, 50); rogue.exp -= 2; add_exp(1); } drain_life() { if (!rand_percent(25) || (rogue.hp_max<=30) || (rogue.hp_current<10)) { return; } message("you feel weaker", 0); rogue.hp_max--; rogue.hp_current--; if (rand_percent(50)) { if (rogue.strength_current >= 5) { rogue.strength_current--; if (rand_percent(50)) { rogue.strength_max--; } } } print_stats(); } m_confuse(monster) object *monster; { char msg[80]; char *monster_name(); if (monster->identified) { return(0); } if (!can_see(monster->row, monster->col)) { return(0); } if (rand_percent(45)) { monster->identified = 1; return(0); } if (rand_percent(55)) { monster->identified = 1; sprintf(msg, "the gaze of the %s has confused you", monster_name(monster)); message(msg, 1); confuse(); return(1); } return(0); } flame_broil(monster) object *monster; { short row, col; if (!can_see(monster->row, monster->col)) { return(0); } if (rand_percent(50)) { return(0); } if (!rogue_is_around(monster->row, monster->col)) { row = monster->row; col = monster->col; get_closer(&row, &col, rogue.row, rogue.col); standout(); do { mvaddch(row, col, '*'); refresh(); get_closer(&row, &col, rogue.row, rogue.col); } while ((row != rogue.row) || (col != rogue.col)); standend(); row = monster->row; col = monster->col; get_closer(&row, &col, rogue.row, rogue.col); do { mvaddch(row, col, get_room_char(screen[row][col], row, col)); refresh(); get_closer(&row, &col, rogue.row, rogue.col); } while ((row != rogue.row) || (col != rogue.col)); } monster_hit(monster, "flame"); return(1); } get_closer(row, col, trow, tcol) short *row, *col; short trow, tcol; { if (*row < trow) { (*row)++; } else if (*row > trow) { (*row)--; } if (*col < tcol) { (*col)++; } else if (*col > tcol) { (*col)--; } } SHAR_EOF cat - << \SHAR_EOF > throw.c #include #include "object.h" #include "move.h" #include "monster.h" extern short current_room; extern char *CURSE_MESSAGE; extern char hit_message[]; throw() { short wch; short first_miss = 1, f = 1; object *weapon, *get_letter_object(); short dir, row, col; object *monster, *get_thrown_at_monster(); while (!is_direction(dir = getchar())) { putchar(7); fflush(stdout); if (first_miss) { message("direction? ", 0); first_miss = 0; } } if (dir == CANCEL) { check_message(); return; } if ((wch = get_pack_letter("throw what?", WEAPON)) == CANCEL) { check_message(); return; } check_message(); if (!(weapon = get_letter_object(wch))) { message("no such item.", 0); return; } if (weapon->what_is != WEAPON) { wch = get_rand(0, 2); switch(wch) { case 0: message("if you don't want it, drop it!", 0); break; case 1: message("throwing that would do noone any good", 0); break; case 2: message("why would you want to throw that?", 0); break; } return; } if ((weapon == rogue.weapon) && (weapon->is_cursed)) { message(CURSE_MESSAGE, 0); return; } row = rogue.row; col = rogue.col; monster = get_thrown_at_monster(dir, &row, &col); mvaddch(rogue.row, rogue.col, rogue.fchar); refresh(); if (can_see(row, col) && ((row != rogue.row) || (col != rogue.col))) { mvaddch(row, col, get_room_char(screen[row][col], row, col)); } if (monster) { wake_up(monster); check_orc(monster); if (!throw_at_monster(monster, weapon)) { f = flop_weapon(weapon, row, col); } } else { f = flop_weapon(weapon, row, col); } vanish(weapon, 1); } throw_at_monster(monster, weapon) object *monster, *weapon; { short damage, hit_chance; char *name_of(); short t; hit_chance = get_hit_chance(weapon); t = weapon->quantity; weapon->quantity = 1; sprintf(hit_message, "the %s", name_of(weapon)); weapon->quantity = t; if (!rand_percent(hit_chance)) { strcat(hit_message, "misses "); return(0); } strcat(hit_message, "hit "); damage = get_weapon_damage(weapon); if (((weapon->which_kind == ARROW) && (rogue.weapon && (rogue.weapon->which_kind == BOW))) || ((weapon->which_kind == SHURIKEN) && (rogue.weapon == weapon))) { damage += get_weapon_damage(rogue.weapon); damage = ((damage * 2) / 3); } monster_damage(monster, damage); return(1); } object *get_thrown_at_monster(dir, row, col) short dir; short *row, *col; { object *object_at(); short orow, ocol; short i; orow = *row; ocol = *col; for (i = 0; i < 24; i++) { get_dir_rc(dir, row, col); if ((screen[*row][*col] == BLANK) || (screen[*row][*col] & (HORWALL | VERTWALL))) { *row = orow; *col = ocol; return(0); } if ((i != 0) && can_see(orow, ocol)) { mvaddch(orow, ocol, get_room_char(screen[orow][ocol], orow, ocol)); } if (can_see(*row, *col)) { if (!(screen[*row][*col] & MONSTER)) { mvaddch(*row, *col, ')'); } refresh(); } orow = *row; ocol = *col; if (screen[*row][*col] & MONSTER) { if (!hiding_xeroc(*row, *col)) { return(object_at(&level_monsters, *row, *col)); } } if (screen[*row][*col] & TUNNEL) { i += 2; } } return(0); } flop_weapon(weapon, row, col) object *weapon; short row, col; { object *new_weapon, *get_an_object(); short i, j, r, c, found = 0, inc1, inc2; char msg[80]; inc1 = get_rand(0, 1) ? 1 : -1; inc2 = get_rand(0, 1) ? 1 : -1; r = row; c = col; if ((screen[r][c] & ~(FLOOR | TUNNEL | DOOR)) || ((row == rogue.row) && (col == rogue.col))) { for (i = inc1; i != (2 * -inc1); i -= inc1) { for (j = inc2; j != (2 * -inc2); j -= inc2) { r = row + i; c = col + j; if ((r > (LINES-2)) || (r < MIN_ROW) || (c > (COLS-1)) || (c < 0)) { continue; } if (!screen[r][c]) continue; if ((screen[r][c] & ~(FLOOR|TUNNEL|DOOR)) || ((r == rogue.row) && (c == rogue.col))) { continue; } found = 1; goto FOUND; } } } else { found = 1; } FOUND: if (found) { new_weapon = get_an_object(); *new_weapon = *weapon; new_weapon->quantity = 1; new_weapon->row = r; new_weapon->col = c; add_mask(r, c, WEAPON); add_to_pack(new_weapon, &level_objects, 0); if (can_see(r, c)) { mvaddch(r, c, get_room_char(screen[r][c], r, c)); } } else { short t; t = weapon->quantity; weapon->quantity = 1; sprintf(msg, "the %svanishes as it hits the ground", name_of(weapon)); weapon->quantity = t; message(msg, 0); } return(found); } SHAR_EOF cat - << \SHAR_EOF > use.c #include #include "object.h" #include "move.h" #include "monster.h" #include "room.h" short halluc = 0; short blind = 0; short confused = 0; short detect_monster = 0; extern short being_held; char *strange_feeling = "you have a strange feeling for a moment, then it passes"; extern char *hunger_str; extern short current_room; extern int level_points[]; quaff() { short ch, i; object *obj, *get_letter_object(); char msg[SCOLS]; ch = get_pack_letter("quaff what? ", POTION); if (ch == CANCEL) { return; } if (!(obj = get_letter_object(ch))) { message("no such item.", 0); return; } if (obj->what_is != POTION) { message("you can't drink that", 0); return; } switch(obj->which_kind) { case INCREASE_STRENGTH: message("you feel stronger now, what bulging muscles!", 0); rogue.strength_current++; if (rogue.strength_current > rogue.strength_max) { rogue.strength_max = rogue.strength_current; } break; case RESTORE_STRENGTH: rogue.strength_current = rogue.strength_max; message("this tastes great, you feel warm all over", 0); break; case HEALING: message("you begin to feel better", 0); potion_heal(0); break; case EXTRA_HEALING: message("you begin to feel much better", 0); potion_heal(1); break; case POISON: rogue.strength_current -= get_rand(1, 3); if (rogue.strength_current < 0) { rogue.strength_current = 0; } message("you feel very sick now", 0); if (halluc) { unhallucinate(); } break; case RAISE_LEVEL: add_exp((level_points[rogue.exp-1]-rogue.exp_points)+1); break; case BLINDNESS: go_blind(); break; case HALLUCINATION: message("oh wow, everything seems so cosmic", 0); halluc += get_rand(500, 800); break; case DETECT_MONSTER: if (level_monsters.next_object) { show_monsters(); } else { message(strange_feeling, 0); } detect_monster = 1; break; case DETECT_OBJECTS: if (level_objects.next_object) { if (!blind) { show_objects(); } } else { message(strange_feeling, 0); } break; case CONFUSION: message((halluc ? "what a trippy feeling" : "you feel confused"), 0); confuse(); break; } print_stats(); if (id_potions[obj->which_kind].id_status != CALLED) { id_potions[obj->which_kind].id_status = IDENTIFIED; } vanish(obj, 1); } read_scroll() { short ch; object *obj, *get_letter_object(); char msg[SCOLS]; char *get_ench_color(); ch = get_pack_letter("read what? ", SCROLL); if (ch == CANCEL) { return; } if (!(obj = get_letter_object(ch))) { message("no such item.", 0); return; } if (obj->what_is != SCROLL) { message("you can't read that", 0); return; } switch(obj->which_kind) { case SCARE_MONSTER: message("you hear a maniacal laughter in the distance", 0); break; case HOLD_MONSTER: hold_monster(); break; case ENCHANT_WEAPON: if (rogue.weapon) { sprintf(msg, "your %sglows %sfor a moment", id_weapons[rogue.weapon->which_kind].title, get_ench_color()); message(msg, 0); if (get_rand(0, 1) == 1) { rogue.weapon->to_hit_enchantment++; } else { rogue.weapon->damage_enchantment++; } rogue.weapon->is_cursed = 0; } else { message("your hands tingle", 0); } break; case ENCHANT_ARMOR: if (rogue.armor) { sprintf(msg, "your armor glows %sfor a moment", get_ench_color()); message(msg, 0); rogue.armor->damage_enchantment++; rogue.armor->is_cursed = 0; print_stats(); } else { message("your skin crawls", 0); } break; case IDENTIFY: message("this is a scroll of identify", 0); message("what would you like to identify?", 0); obj->identified = 1; id_scrolls[obj->which_kind].id_status = IDENTIFIED; identify(); break; case TELEPORT: teleport(); break; case SLEEP: sleep_scroll(); break; case PROTECT_ARMOR: if (rogue.armor) { message( "your armor is covered by a shimmering gold shield", 0); rogue.armor->is_protected = 1; } else { message("your acne seems to have disappeared", 0); } break; case REMOVE_CURSE: message( "you feel as though someone is watching over you", 0); if (rogue.armor) { rogue.armor->is_cursed = 0; } if (rogue.weapon) { rogue.weapon->is_cursed = 0; } break; case CREATE_MONSTER: create_monster(); break; case AGGRAVATE_MONSTER: aggravate(); break; } if (id_scrolls[obj->which_kind].id_status != CALLED) { id_scrolls[obj->which_kind].id_status = IDENTIFIED; } vanish(obj, 1); } vanish(obj, rm) object *obj; short rm; { if (obj->quantity > 1) { obj->quantity--; } else { remove_from_pack(obj, &rogue.pack); make_avail_ichar(obj->ichar); free(obj); } if (rm) { register_move(); } } potion_heal(extra) { float ratio; short add; ratio = ((float)rogue.hp_current) / rogue.hp_max; if (ratio >= 0.90) { rogue.hp_max += (extra + 1); rogue.hp_current = rogue.hp_max; } else { if (ratio < 30.00) { ratio = 30.00; } if (extra) { ratio += ratio; } add = (short)(ratio*((float)rogue.hp_max-rogue.hp_current)); rogue.hp_current += add; if (rogue.hp_current > rogue.hp_max) { rogue.hp_current = rogue.hp_max; } } if (blind) { unblind(); } if (confused && extra) { unconfuse(); } if (confused) { confused = ((confused - 9) / 2); if (confused <= 0) { unconfuse(); } } if (halluc && extra) { unhallucinate(); } else if (halluc) { halluc = (halluc/2) + 1; } } identify() { short ch; object *obj, *get_letter_object(); struct identify *id_table, *get_id_table(); char description[SCOLS]; AGAIN: ch = get_pack_letter("identify what? ", IS_OBJECT); if (ch == CANCEL) { return; } if (!(obj = get_letter_object(ch))) { message("no such item, try again", 0); message("", 0); check_message(); goto AGAIN; } obj->identified = 1; if (obj->what_is & (SCROLL | POTION | WEAPON | ARMOR | WAND)) { id_table = get_id_table(obj); id_table[obj->which_kind].id_status = IDENTIFIED; } get_description(obj, description); message(description, 0); } eat() { short ch; short moves; object *obj, *get_letter_object(); char msg[SCOLS]; ch = get_pack_letter("eat what? ", FOOD); if (ch == CANCEL) { return; } if (!(obj = get_letter_object(ch))) { message("no such item.", 0); return; } if (obj->what_is != FOOD) { message("you can't eat that", 0); return; } moves = get_rand(800, 1000); if (moves >= 900) { message("yum, that tasted good", 0); } else { message("yuk, that food tasted awful", 0); add_exp(3); } rogue.moves_left /= 2; rogue.moves_left += moves; hunger_str = ""; print_stats(); vanish(obj, 1); } hold_monster() { short i, j; short mcount = 0; object *monster, *object_at(); short row, col; for (i = -2; i <= 2; i++) { for (j = -2; j <= 2; j++) { row = rogue.row + i; col = rogue.col + j; if ((row < MIN_ROW) || (row > (LINES-2)) || (col < 0) || (col > (COLS-1))) { continue; } if (screen[row][col] & MONSTER) { monster = object_at(&level_monsters, row, col); monster->m_flags |= IS_ASLEEP; monster->m_flags &= (~WAKENS); mcount++; } } } if (mcount == 0) { message("you feel a strange sense of loss", 0); } else if (mcount == 1) { message("the monster freezes", 0); } else { message("the monsters around you freeze", 0); } } teleport() { if (current_room >= 0) { darken_room(current_room); } else { mvaddch(rogue.row, rogue.col, get_room_char(screen[rogue.row][rogue.col], rogue.row, rogue.col)); } put_player(); light_up_room(); being_held = 0; } hallucinate() { object *obj; short ch; if (blind) return; obj = level_objects.next_object; while (obj) { move(obj->row, obj->col); ch = inch(); if (((ch < 'A') || (ch > 'Z')) && ((obj->row != rogue.row) || (obj->col != rogue.col))) if ((ch != ' ')&&(ch != '.')&&(ch != '#')&&(ch != '+')) { mvaddch(obj->row, obj->col, get_rand_obj_char()); } obj = obj->next_object; } obj = level_monsters.next_object; while (obj) { move(obj->row, obj->col); ch = inch(); if ((ch >= 'A') && (ch <= 'Z')) { mvaddch(obj->row,obj->col,get_rand('A','Z')); } obj = obj->next_object; } } unhallucinate() { halluc = 0; if (current_room == PASSAGE) { light_passage(rogue.row, rogue.col); } else { light_up_room(); } message("everything looks SO boring now", 0); } unblind() { blind = 0; message("the veil of darkness lifts", 0); if (current_room == PASSAGE) { light_passage(rogue.row, rogue.col); } else { light_up_room(); } blind = 0; if (detect_monster) { show_monsters(); } if (halluc) { hallucinate(); } } sleep_scroll() { short i; message("you fall asleep", 0); sleep(1); i = get_rand(4, 10); while (i--) { move_monsters(); } sleep(1); message("you can move again", 0); } go_blind() { short i, j; if (!blind) { message("a cloak of darkness falls around you", 0); } blind += get_rand(500, 800); if (current_room >= 0) { for (i = rooms[current_room].top_row + 1; i < rooms[current_room].bottom_row; i++) { for (j = rooms[current_room].left_col + 1; j < rooms[current_room].right_col; j++) { mvaddch(i, j, ' '); } } } mvaddch(rogue.row, rogue.col, rogue.fchar); refresh(); } char *get_ench_color() { if (halluc) { return(id_potions[get_rand(0, POTIONS-1)].title); } return("blue "); } confuse() { confused = get_rand(12, 22); } unconfuse() { char msg[80]; confused = 0; sprintf(msg, "you feel less %s now", (halluc ? "trippy" : "confused")); message(msg, 0); } SHAR_EOF cat - << \SHAR_EOF > zap.c #include #include "object.h" #include "move.h" #include "monster.h" extern short current_room, being_held, current_level; zapp() { short wch; short first_miss = 1; object *wand, *get_letter_object(); short dir, row, col; object *monster, *get_zapped_monster(); while (!is_direction(dir = getchar())) { putchar(7); fflush(stdout); if (first_miss) { message("direction? ", 0); first_miss = 0; } } if (dir == CANCEL) { check_message(); return; } if ((wch = get_pack_letter("zap with what?", WAND)) == CANCEL) { check_message(); return; } check_message(); if (!(wand = get_letter_object(wch))) { message("no such item.", 0); return; } if (wand->what_is != WAND) { message("you can't zap with that", 0); return; } if (wand->class <= 0) { message("nothing happens", 0); goto RM; } else { wand->class--; } row = rogue.row; col = rogue.col; monster = get_zapped_monster(dir, &row, &col); if (monster != 0) { wake_up(monster); zap_monster(monster, wand->which_kind); } RM: register_move(); } object *get_zapped_monster(dir, row, col) short dir; short *row, *col; { object *object_at(); short orow, ocol; short i; for (;;) { orow = *row; ocol = *col; get_dir_rc(dir, row, col); if (((*row == orow) && (*col == ocol)) || (screen[*row][*col] & (HORWALL | VERTWALL)) || (screen[*row][*col] == BLANK)) { return(0); } if (screen[*row][*col] & MONSTER) { if (!hiding_xeroc(*row, *col)) { return(object_at(&level_monsters, *row, *col)); } } } } zap_monster(monster, kind) object *monster; short kind; { short row, col; struct object *nm; row = monster->row; col = monster->col; nm = monster->next_object; switch(kind) { case SLOW_MONSTER: if (monster->m_flags & HASTED) { monster->m_flags &= (~HASTED); } else { monster->quiver = 0; monster->m_flags |= SLOWED; } break; case HASTE_MONSTER: if (monster->m_flags & SLOWED) { monster->m_flags &= (~SLOWED); } else { monster->m_flags |= HASTED; } break; case TELEPORT_AWAY: teleport_away(monster); break; case KILL_MONSTER: rogue.exp_points -= monster->kill_exp; monster_damage(monster, monster->quantity); break; case INVISIBILITY: monster->m_flags |= IS_INVIS; mvaddch(row, col, get_monster_char(monster)); break; case POLYMORPH: if (monster->ichar == 'F') { being_held = 0; } MA: *monster = monster_tab[get_rand(0, MONSTERS-1)]; if ((monster->ichar == 'X') && ((current_level < XEROC1) || (current_level > XEROC2))) { goto MA; } monster->what_is = MONSTER; monster->row = row; monster->col = col; monster->next_object = nm; wake_up(monster); if (can_see(row, col)) { mvaddch(row, col, get_monster_char(monster)); } break; case PUT_TO_SLEEP: monster->m_flags |= IS_ASLEEP; monster->m_flags &= (~WAKENS); break; case DO_NOTHING: message("nothing happens", 0); break; } } teleport_away(monster) object *monster; { short row, col; if (monster->ichar == 'F') { being_held = 0; } get_rand_row_col(&row, &col, (FLOOR | TUNNEL | IS_OBJECT)); remove_mask(monster->row, monster->col, MONSTER); mvaddch(monster->row, monster->col, get_room_char(screen[monster->row][monster->col], monster->row, monster->col)); monster->row = row; monster->col = col; add_mask(row, col, MONSTER); if (can_see(row, col)) { mvaddch(row, col, get_monster_char(monster)); } } SHAR_EOF