Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!burl!ulysses!gamma!epsilon!zeta!sabre!petrus!bellcore!decvax!decwrl!glacier!hplabs!tektronix!teklds!zeus!tims From: tims@zeus.UUCP (Tim Stoehr) Newsgroups: net.sources.games Subject: Rogue clone, again(groan!), in small pieces. Part 2 of 3. Message-ID: <56@zeus.UUCP> Date: Sun, 16-Mar-86 15:34:20 EST Article-I.D.: zeus.56 Posted: Sun Mar 16 15:34:20 1986 Date-Received: Wed, 19-Mar-86 04:08:40 EST Distribution: net Organization: Tektronix, Beaverton OR Lines: 2065 #!/bin/sh-----cut here-----cut here-----cut here-----cut here----- # shar: Shell Archiver # Run the following text with /bin/sh to create: # monster.c # move.c # object.c # pack.c echo shar: extracting monster.c cat - << \SHAR_EOF > monster.c #include #include "monster.h" #include "object.h" #include "room.h" #include "move.h" extern short current_level; extern short current_room, party_room; extern short detect_monster; extern short blind, halluc; char *monster_names[] = { "aquatar", "bat", "centaur", "dragon", "emu", "venus fly-trap", "griffin", "hobgoblin", "ice monster", "jabberwock", "kestrel", "leprechaun", "medusa", "nymph", "orc", "phantom", "quasit", "rattlesnake", "snake", "troll", "black unicorn", "vampire", "wraith", "xeroc", "yeti", "zombie" }; object monster_tab[MONSTERS] = { {(IS_ASLEEP|WAKENS|WANDERS),"0d0",25,'A',20,9,18,100,0,0}, {(IS_ASLEEP|WANDERS|FLITS),"1d3",10,'B',2,1,8,60,0,0}, {(IS_ASLEEP|WANDERS),"3d3/2d5",30,'C',15,7,16,85,0,10}, {(IS_ASLEEP|WAKENS),"4d5/3d9",128,'D',5000,21,126,100,0,90}, {(IS_ASLEEP|WAKENS),"1d3",11,'E',2,1,7,65,0,0}, {(0),"0d0",32,'F',91,12,126,80,0,0}, {(IS_ASLEEP|WAKENS|WANDERS|FLIES),"5d4/4d5",92,'G',2000,20,126,85,0,10}, {(IS_ASLEEP|WAKENS|WANDERS),"1d3/1d3",17,'H',3,1,10,67,0,0}, {(IS_ASLEEP),"0d0",15,'I',5,2,11,68,0,0}, {(IS_ASLEEP|WANDERS),"3d10/3d4",125,'J',3000,21,126,100,0,0}, {(IS_ASLEEP|WAKENS|WANDERS|FLIES),"1d4",10,'K',2,1,6,60,0,0}, {(IS_ASLEEP),"0d0",25,'L',18,6,16,75,0,0}, {(IS_ASLEEP|WAKENS|WANDERS),"4d4/3d7",92,'M',250,18,126,85,0,25}, {(IS_ASLEEP),"0d0",25,'N',37,10,19,75,0,100}, {(IS_ASLEEP|WANDERS|WAKENS),"1d6",25,'O',5,4,13,70,0,10}, {(IS_ASLEEP|IS_INVIS|WANDERS|FLITS),"5d4",76,'P',120,15,23,80,0,50}, {(IS_ASLEEP|WAKENS|WANDERS),"3d5",30,'Q',20,8,17,78,0,20}, {(IS_ASLEEP|WAKENS|WANDERS),"2d5",19,'R',10,3,12,70,0,0}, {(IS_ASLEEP|WAKENS|WANDERS),"1d3",8,'S',2,1,9,50,0,0}, {(IS_ASLEEP|WAKENS|WANDERS),"4d6",64,'T',125,13,22,75,0,33}, {(IS_ASLEEP|WAKENS|WANDERS),"4d9",88,'U',200,17,26,85,0,33}, {(IS_ASLEEP|WAKENS|WANDERS),"1d14",40,'V',350,19,126,85,0,18}, {(IS_ASLEEP|WANDERS),"2d7",42,'W',55,14,23,75,0,0}, {(IS_ASLEEP),"4d6",42,'X',110,XEROC1,XEROC2,75,0,0}, {(IS_ASLEEP|WANDERS),"3d6",33,'Y',50,11,20,80,0,20}, {(IS_ASLEEP|WAKENS|WANDERS),"1d7",20,'Z',8,5,14,69,0,0} }; object level_monsters; put_monsters() { short i; short n; object *monster, *get_rand_monster(); n = get_rand(3, 7); for (i = 0; i < n; i++) { monster = get_rand_monster(); if ((monster->m_flags & WANDERS) && rand_percent(50)) { wake_up(monster); } put_monster_rand_location(monster); add_to_pack(monster, &level_monsters, 0); } } object *get_rand_monster() { object *monster, *get_an_object(); short mn; monster = get_an_object(); for (;;) { mn = get_rand(0, MAXMONSTER-1); if ((current_level >= monster_tab[mn].is_protected) && (current_level <= monster_tab[mn].is_cursed)) { break; } } *monster = monster_tab[mn]; monster->what_is = MONSTER; if (monster->ichar == 'X') { monster->identified = get_rand_obj_char(); } if (current_level > (AMULET_LEVEL + 2)) { monster->m_flags |= HASTED; } monster->trow = -1; return(monster); } move_monsters() { object *monster; short flew; monster = level_monsters.next_object; while (monster) { if (monster->m_flags & HASTED) { mv_monster(monster, rogue.row, rogue.col); } else if (monster->m_flags & SLOWED) { monster->quiver = !monster->quiver; if (monster->quiver) { goto NM; } } flew = 0; if ((monster->m_flags & FLIES) && !monster_can_go(monster, rogue.row, rogue.col)) { flew = 1; mv_monster(monster, rogue.row, rogue.col); } if (!flew || !monster_can_go(monster, rogue.row, rogue.col)) { mv_monster(monster, rogue.row, rogue.col); } NM: monster = monster->next_object; } } fill_room_with_monsters(rn, n) { short i; short row, col; object *monster, *get_rand_monster(); n += n/2; for (i = 0; i < n; i++) { if (no_room_for_monster(rn)) break; 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] & MONSTER); monster = get_rand_monster(); put_monster_at(row, col, monster); } } get_monster_char_row_col(row, col) { object *monster, *object_at(); short retval; monster = object_at(&level_monsters, row, col); if ((!detect_monster && (monster->m_flags & IS_INVIS)) || blind) { retval = get_room_char((screen[row][col] & ~MONSTER),row,col); return(retval); } if ((monster->ichar == 'X') && monster->identified) { return(monster->identified); } return(monster->ichar); } get_monster_char(monster) object *monster; { short retval; if ((!detect_monster && (monster->m_flags & IS_INVIS)) || blind) { retval = get_room_char((screen[monster->row][monster->col] & ~MONSTER), monster->row, monster->col); return(retval); } if ((monster->ichar == 'X') && monster->identified) { return(monster->identified); } return(monster->ichar); } mv_monster(monster, row, col) register object *monster; short row, col; { short i, n; char tried[6]; if (monster->m_flags & IS_ASLEEP) { if ((monster->m_flags & WAKENS) && rogue_is_around(monster->row, monster->col) && rand_percent(WAKE_PERCENT)) { wake_up(monster); } return; } if ((monster->m_flags & FLITS) && flit(monster)) { return; } if ((monster->ichar == 'F') && !monster_can_go(monster, rogue.row, rogue.col)) { return; } if ((monster->ichar == 'I') && monster->identified) { return; } if ((monster->ichar == 'M') && m_confuse(monster)) { return; } if (monster_can_go(monster, rogue.row, rogue.col)) { monster_hit(monster, 0); return; } if ((monster->ichar == 'D') && flame_broil(monster)) { return; } if ((monster->ichar == 'O') && orc_gold(monster)) { return; } if ((monster->trow == monster->row) && (monster->tcol == monster->col)) { monster->trow = -1; } else if (monster->trow != -1) { row = monster->trow; col = monster->tcol; } if (monster->row > row) { row = monster->row - 1; } else if (monster->row < row) { row = monster->row + 1; } if ((screen[row][monster->col] & DOOR) && mtry(monster, row, monster->col)) { return; } if (monster->col > col) { col = monster->col - 1; } else if (monster->col < col) { col = monster->col + 1; } if ((screen[monster->row][col] & DOOR) && mtry(monster, monster->row, col)) { return; } if (mtry(monster, row, col)) { return; } for (i = 0; i <= 5; i++) tried[i] = 0; for (i = 0; i < 6; i++) { NEXT_TRY: n = get_rand(0, 5); switch(n) { case 0: if (!tried[n] && mtry(monster, row, monster->col-1)) { return; } break; case 1: if (!tried[n] && mtry(monster, row, monster->col)) { return; } break; case 2: if (!tried[n] && mtry(monster, row, monster->col+1)) { return; } break; case 3: if (!tried[n] && mtry(monster, monster->row-1, col)) { return; } break; case 4: if (!tried[n] && mtry(monster, monster->row, col)) { return; } break; case 5: if (!tried[n] && mtry(monster, monster->row+1, col)) { return; } break; } if (!tried[n]) { tried[n] = 1; } else { goto NEXT_TRY; } } } mtry(monster, row, col) register object *monster; register short row, col; { if (monster_can_go(monster, row, col)) { move_monster_to(monster, row, col); return(1); } return(0); } move_monster_to(monster, row, col) register object *monster; register short row, col; { short c; add_mask(row, col, MONSTER); remove_mask(monster->row, monster->col, MONSTER); c = mvinch(monster->row, monster->col); if ((c >= 'A') && (c <= 'Z')) { mvaddch(monster->row, monster->col, get_room_char(screen[monster->row][monster->col], monster->row, monster->col)); } if (!blind && (detect_monster || can_see(row, col))) { if ((!(monster->m_flags & IS_INVIS) || detect_monster)) { mvaddch(row, col, get_monster_char(monster)); } } if ((screen[row][col] & DOOR) && (get_room_number(row, col) != current_room) && (screen[monster->row][monster->col] == FLOOR)) { if (!blind) mvaddch(monster->row, monster->col, ' '); } if (screen[row][col] & DOOR) { door_course(monster, (screen[monster->row][monster->col] & TUNNEL), row, col); } else { monster->row = row; monster->col = col; } } monster_can_go(monster, row, col) register object *monster; register short row, col; { object *obj, *object_at(); short dr, dc; dr = monster->row - row; /* check if move distance > 1 */ if ((dr >= 2) || (dr <= -2)) return(0); dc = monster->col - col; if ((dc >= 2) || (dc <= -2)) return(0); if ((!screen[monster->row][col]) || (!screen[row][monster->col])) { return(0); } if ((!is_passable(row, col)) || (screen[row][col] & MONSTER)) { return(0); } if ((monster->row!=row)&&(monster->col!=col)&&((screen[row][col]&DOOR) || (screen[monster->row][monster->col]&DOOR))) { return(0); } if (!(monster->m_flags & FLITS) && !(monster->m_flags & CAN_GO) && (monster->trow == -1)) { if ((monster->row < rogue.row) && (row < monster->row)) return(0); if ((monster->row > rogue.row) && (row > monster->row)) return(0); if ((monster->col < rogue.col) && (col < monster->col)) return(0); if ((monster->col > rogue.col) && (col > monster->col)) return(0); } if (screen[row][col] & SCROLL) { obj = object_at(&level_objects, row, col); if (obj->which_kind == SCARE_MONSTER) { return(0); } } return(1); } wake_up(monster) object *monster; { monster->m_flags &= (~IS_ASLEEP); } wake_room(rn, entering, row, col) { object *monster; short wake_percent; wake_percent = (rn == party_room) ? PARTY_WAKE_PERCENT : WAKE_PERCENT; monster = level_monsters.next_object; while (monster) { if (((monster->m_flags & WAKENS) || (rn == party_room)) && (rn == get_room_number(monster->row, monster->col))) { if ((monster->ichar != 'X') && (rn == party_room)) { monster->m_flags |= WAKENS; } if (entering) { monster->trow = -1; } else { monster->trow = row; monster->tcol = col; } if (rand_percent(wake_percent) && (monster->m_flags & WAKENS)) { if (monster->ichar != 'X') { wake_up(monster); } } } monster = monster->next_object; } } char *monster_name(monster) object *monster; { short ch; if (blind || ((monster->m_flags & IS_INVIS) && !detect_monster)) { return("something"); } if (halluc) { ch = get_rand('A', 'Z') - 'A'; return(monster_names[ch]); } ch = monster->ichar - 'A'; return(monster_names[ch]); } rogue_is_around(row, col) { short rdif, cdif, retval; rdif = row - rogue.row; cdif = col - rogue.col; retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1); return(retval); } start_wanderer() { object *monster, *get_rand_monster(); short row, col, i; ANOTHER: monster = get_rand_monster(); if ((!(monster->m_flags & WAKENS)) && (!(monster->m_flags & WANDERS))) { free(monster); goto ANOTHER; } wake_up(monster); for (i = 0; i < 12; i++) { get_rand_row_col(&row, &col, (FLOOR | TUNNEL | IS_OBJECT)); if (!can_see(row, col)) { put_monster_at(row, col, monster); return; } } } show_monsters() { object *monster; if (blind) return; monster = level_monsters.next_object; while (monster) { mvaddch(monster->row, monster->col, monster->ichar); if (monster->ichar == 'X') { monster->identified = 0; } monster = monster->next_object; } } create_monster() { short row, col; short i, j, inc1, inc2; short found = 0; object *monster; inc1 = get_rand(0, 1) ? 1 : -1; inc2 = get_rand(0, 1) ? 1 : -1; for (i = inc1; i != (2 * -inc1); i -= inc1) { for (j = inc2; j != (2 * -inc2); j -= inc2) { if (!i && !j) continue; 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)) && (screen[row][col] & (FLOOR|TUNNEL|STAIRS))) { found = 1; goto FOUND; } } } FOUND: if (found) { monster = get_rand_monster(); put_monster_at(row, col, monster); mvaddch(row, col, get_monster_char(monster)); if (monster->m_flags & WANDERS) { wake_up(monster); } } else { message("you hear a faint cry of anguish in the distance",0); } } put_monster_at(row, col, monster) object *monster; { monster->row = row; monster->col = col; add_mask(row, col, MONSTER); add_to_pack(monster, &level_monsters, 0); } can_see(row, col) { short retval; retval = !blind && ((get_room_number(row, col) == current_room) || (rogue_is_around(row, col))); return(retval); } flit(monster) object *monster; { short inc1, inc2; short i, j, row, col; if (!rand_percent(FLIT_PERCENT)) { return(0); } inc1 = get_rand(0, 1) ? 1 : -1; inc2 = get_rand(0, 1) ? 1 : -1; if (rand_percent(10)) { return(1); } for (i = inc1; i != (2*(0-inc1)); i+=(0-inc1)) { for (j = inc2; j != (2*(0-inc2)); j+=(0-inc2)) { row = monster->row + i; col = monster->col + j; if ((row == rogue.row) && (col == rogue.col)) { continue; } if (mtry(monster, row, col)) { return(1); } } } return(1); } put_monster_rand_location(monster) object *monster; { short row, col; get_rand_row_col(&row, &col, (FLOOR | TUNNEL | IS_OBJECT)); add_mask(row, col, MONSTER); monster->row = row; monster->col = col; } get_rand_obj_char() { short r; char *rs = "%!?]/):*"; r = get_rand(0, 7); return(rs[r]); } no_room_for_monster(rn) { short i, j; for (i = rooms[rn].left_col+1; i < rooms[rn].right_col; i++) { for (j = rooms[rn].top_row+1; j < rooms[rn].bottom_row; j++) { if (!(screen[i][j] & MONSTER)) { return(0); } } } return(1); } aggravate() { struct object *monster; message("you hear a high pitched humming noise"); monster = level_monsters.next_object; while (monster) { wake_up(monster); if (monster->ichar == 'X') { monster->identified = 0; } monster = monster->next_object; } } monster_can_see(monster, row, col) object *monster; { short rn, rdif, cdif, retval; rn = get_room_number(row, col); if ((rn != NO_ROOM) && (rn == get_room_number(monster->row, monster->col))) { return(1); } rdif = row - monster->row; cdif = col - monster->col; retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1); return(retval); } mv_aquatars() { object *monster; monster = level_monsters.next_object; while (monster) { if (monster->ichar == 'A') { mv_monster(monster, rogue.row, rogue.col); } monster = monster->next_object; } } SHAR_EOF echo shar: extracting move.c cat - << \SHAR_EOF > move.c #include #include "object.h" #include "room.h" #include "move.h" #include "monster.h" extern short current_room, halluc, detect_monster, blind, being_held; extern short confused, interrupted, has_amulet; extern char *hunger_str; single_move_rogue(dirch, pickup) { short row, col; object *obj, *object_at(), *pick_up(); char description[SCOLS]; short n, status; row = rogue.row; col = rogue.col; if (being_held) { get_dir_rc(dirch, &row, &col); if (!(screen[row][col] & MONSTER)) { message("you are being held", 1); return(MOVE_FAILED); } } row = rogue.row; col = rogue.col; if (confused) { dirch = get_rand_dir(); } switch(dirch) { case 'h': col--; break; case 'j': row++; break; case 'k': row--; break; case 'l': col++; break; case 'b': col--; row++; break; case 'y': col--; row--; break; case 'u': col++; row--; break; case 'n': col++; row++; break; } if (screen[row][col] & MONSTER) { rogue_hit(object_at(&level_monsters, row, col)); register_move(); return(MOVE_FAILED); } if (!can_move(rogue.row, rogue.col, row, col)) { return(MOVE_FAILED); } if (screen[row][col] & DOOR) { if (current_room == PASSAGE) { current_room = get_room_number(row, col); light_up_room(); wake_room(current_room, 1, row, col); } else { light_passage(row, col); } } else if ((screen[rogue.row][rogue.col] & DOOR) && (screen[row][col] & TUNNEL)) { light_passage(row, col); wake_room(current_room, 0, row, col); darken_room(current_room); current_room = PASSAGE; } else if (screen[row][col] & TUNNEL) { light_passage(row, col); } mvaddch(rogue.row, rogue.col, get_room_char(screen[rogue.row][rogue.col], rogue.row, rogue.col)); mvaddch(row, col, rogue.fchar); rogue.row = row; rogue.col = col; if (screen[row][col] & CAN_PICK_UP) { if (pickup) { if (obj = pick_up(row, col, &status)) { get_description(obj, description); if (obj->what_is == GOLD) { free(obj); goto NOT_IN_PACK; } } else if (!status) { goto MVED; } else { goto MOVE_ON; } } else { MOVE_ON: obj = object_at(&level_objects, row, col); strcpy(description, "moved onto "); get_description(obj, description+11); goto NOT_IN_PACK; } n = strlen(description); description[n] = '('; description[n+1] = obj->ichar; description[n+2] = ')'; description[n+3] = 0; NOT_IN_PACK: message(description, 1); register_move(); return(STOPPED_ON_SOMETHING); } if ((screen[row][col] & DOOR) || (screen[row][col] & STAIRS)) { register_move(); return(STOPPED_ON_SOMETHING); } MVED: if (register_move()) { /* fainted from hunger */ return(STOPPED_ON_SOMETHING); } return((confused ? STOPPED_ON_SOMETHING : MOVED)); } multiple_move_rogue(dirch) { short row, col; short m; switch(dirch) { case '\010': case '\012': case '\013': case '\014': case '\031': case '\025': case '\016': case '\002': do { row = rogue.row; col = rogue.col; if (((m = single_move_rogue((dirch + 96), 1)) == MOVE_FAILED) || (m == STOPPED_ON_SOMETHING) || interrupted) { break; } } while (!next_to_something(row, col)); break; case 'H': case 'J': case 'K': case 'L': case 'B': case 'Y': case 'U': case 'N': while (!interrupted && single_move_rogue((dirch + 32), 1) == MOVED) ; break; } } is_passable(row, col) { if ((row < MIN_ROW) || (row > (LINES - 2)) || (col < 0) || (col > (COLS-1))) { return(0); } return(screen[row][col] & (FLOOR | TUNNEL | DOOR | STAIRS)); } next_to_something(drow, dcol) { short i, j, i_end, j_end, row, col; short pass_count = 0; if (confused) { return(1); } if (blind) { return(0); } i_end = (rogue.row < (LINES-2)) ? 1 : 0; j_end = (rogue.col < (COLS-1)) ? 1 : 0; for (i = ((rogue.row > MIN_ROW) ? -1 : 0); i <= i_end; i++) { for (j = ((rogue.col > 0) ? -1 : 0); j <= j_end; j++) { if ((i == 0) && (j == 0)) continue; if (((rogue.row+i)==drow)&&((rogue.col+j)==dcol)) { continue; } if(screen[rogue.row+i][rogue.col+j]&(MONSTER|IS_OBJECT))return(1); if ((((i - j) == 1) || ((i - j) == -1)) && (screen[rogue.row+i][rogue.col+j] & TUNNEL)) { if (++pass_count > 1) { return(1); } } row = rogue.row+i; col = rogue.col+j; if ((screen[row][col] & DOOR)||(is_object(row,col))) { if (i == 0 || j == 0) { return(1); } } } } return(0); } can_move(row1, col1, row2, col2) { if (!is_passable(row2, col2)) { return(0); } if ((row1 != row2) && (col1 != col2)) { if ((screen[row1][col1]&DOOR)||(screen[row2][col2]&DOOR)) { return(0); } if ((!screen[row1][col2]) || (!screen[row2][col1])) { return(0); } } return(1); } is_object(row, col) { return(screen[row][col] & IS_OBJECT); } move_onto() { short ch; short first_miss = 1; while (!is_direction(ch = getchar())) { putchar(7); fflush(stdout); if (first_miss) { message("direction? ", 0); first_miss = 0; } } check_message(); if (ch != CANCEL) { single_move_rogue(ch, 0); } } is_direction(c) { return( (c == 'h') || (c == 'j') || (c == 'k') || (c == 'l') || (c == 'b') || (c == 'y') || (c == 'u') || (c == 'n') || (c == CANCEL) ); } is_pack_letter(c) { return(((c >= 'a') && (c <= 'z')) || (c == CANCEL) || (c == LIST)); } check_hunger() { short i, n; short fainted = 0; if (rogue.moves_left == HUNGRY) { hunger_str = "hungry"; message(hunger_str, 0); print_stats(); } if (rogue.moves_left == WEAK) { hunger_str = "weak"; message(hunger_str, 0); print_stats(); } if ((rogue.moves_left) <= FAINT) { if (rogue.moves_left == FAINT) { hunger_str = "faint"; message(hunger_str, 1); print_stats(); } n = get_rand(0, (FAINT - rogue.moves_left)); if (n > 0) { fainted = 1; if (rand_percent(40)) rogue.moves_left++; message("you faint", 1); for (i = 0; i < n; i++) { if (rand_percent(50)) { move_monsters(); } } message("you can move again", 1); } } if (rogue.moves_left <= STARVE) { killed_by(0, STARVATION); } rogue.moves_left--; return(fainted); } register_move() { static short moves = 0; short fainted; if ((rogue.moves_left <= HUNGRY) || !has_amulet) { fainted = check_hunger(); } else { fainted = 0; } move_monsters(); if (++moves >= 80) { moves = 0; start_wanderer(); } if (halluc) { if (!(--halluc)) { unhallucinate(); } else { hallucinate(); } } if (blind) { if (!(--blind)) { unblind(); } } if (confused) { if (!(--confused)) { unconfuse(); } } heal(); return(fainted); } rest(count) { int i; for (i = 0; i < count; i++) { if (interrupted) break; register_move(); } } get_rand_dir() { short d; d = get_rand(1, 8); switch(d) { case 1: return('j'); case 2: return('k'); case 3: return('l'); case 4: return('h'); case 5: return('y'); case 6: return('u'); case 7: return('b'); case 8: return('n'); } } heal() { static short exp = -1, n, c = 0; if (rogue.exp != exp) { exp = rogue.exp; switch(exp) { case 1: n = 20; break; case 2: n = 18; break; case 3: n = 17; break; case 4: n = 14; break; case 5: n = 13; break; case 6: n = 10; break; case 7: n = 9; break; case 8: n = 8; break; case 9: n = 7; break; case 10: n = 4; break; case 11: n = 3; break; case 12: default: n = 2; } } if (rogue.hp_current == rogue.hp_max) { c = 0; return; } if (++c >= n) { c = 0; rogue.hp_current++; if (rogue.hp_current < rogue.hp_max) { if (rand_percent(50)) { rogue.hp_current++; } } print_stats(); } } SHAR_EOF echo shar: extracting object.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 echo shar: extracting pack.c 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; message(prompt, 0); 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