Global pathing = false; Constant P_Sitting 1; Constant P_Standing 2; Constant P_Lying 3; !Constant S_Tiny 1; !Constant S_Small 3; !Constant S_Normal 9; !Constant S_Large 27; !Constant S_Huge 81; Constant W_VLight 1; Constant W_Light 3; Constant W_Normal 9; Constant W_Heavy 27; Constant W_VHeavy 81; Constant PATHING_CANT_GO 1; Constant PATHING_MAP_PLACING 2; Constant PATHING_MAP_DRAWING 3; Constant PATHING_NPC_MOVE 4; !Following code for reading the player's name by Roger Firth Constant NAME_SIZE 32; Array player_name buffer NAME_SIZE; !#ifdef AUTOMAP; !Property map_x; !Property map_y; !Property region_owner; !Property region_next; !#endif; #Ifdef TARGET_ZCODE; [ KeyLine buf max; buf->0 = max; buf->1 = 0; read buf 0; buf->0 = 0; return buf-->0; ]; #Ifnot; ! TARGET_GLULX [ KeyLine buf max; glk($00D0, gg_mainwin, buf+WORDSIZE, max, 0); ! request_line_event while (true) { glk($00C0, gg_event); ! select if (gg_event-->0 == 3 && gg_event-->1 == gg_mainwin) break; } buf-->0 = gg_event-->2; return buf-->0; ]; #Endif; ! TARGET_ [ PrintString buf i; for (i=0 : i0 : i++) print (char) buf->(i+WORDSIZE); ]; [ CapitaliseString buf i c flg; for (i=0,flg=true : i0 : i++) { c = buf->(i+WORDSIZE); if (c >= 'a' && c <= 'z') { if (flg) buf->(i+WORDSIZE) = UpperCase(c); flg = false; } else flg = true; } ]; [ PromptForName; print "^^^^^"; do { do { print "What's your name? "; } until (KeyLine(player_name, NAME_SIZE)); CapitaliseString(player_name); print "Is ~", (PrintString) player_name, "~ correct? "; } until (YesOrNo()); ]; ! End code from Roger Firth class Item with itemdesc nothing, size S_Normal, weight W_Normal, description [ ; switch (metaclass(self.itemdesc)) { nothing: print "I see nothing special about ", (the) self, "."; String: print (string) self.itemdesc; Routine: if (self.itemdesc() == 0) print "I see nothing special about ", (the) self, "."; default: print_ret (The) self, ".description unknown type ", (ZRegion) self.itemdesc; } if (self has container || self has supporter) print " ", (ShowContents) self; if (self provides states && self provides state) print " ", (The) self, " ", (IsOrAre) self, " ", (string) self.&states->(self.state); ""; ]; ! Show contents of obj. If nl is true, print a newline afterwards. returns nl [ ShowContents obj nl; if (obj has container && obj hasnt open && obj has locked) print (The) obj, " is locked."; else if (obj has container && obj hasnt open) print (The) obj, " is closed."; else if (obj has container && child(obj) == 0) print (The) obj, " is empty."; else if (obj has supporter && child(obj) == 0) print (The) obj, " is clear."; else { if (self has supporter) print "On "; else print "Inside "; print (the) obj; WriteListFrom (child(obj), ENGLISH_BIT | RECURSE_BIT | ISARE_BIT); print "."; } if (nl) new_line; return nl; ]; [ ObjState obj ; print (The) obj, " ", (isorare) obj, " ", (string) (obj.&states-->(obj.state)); ]; [ Wornby obj actor ; if (actor == player) return obj in player && obj has worn; return obj in actor && obj has npcworn; ]; class Room with cant_go [ dir count tpath count2; tpath = pathing; if (tpath) print "Huh, pathing not already 0 on entering ", (the) self, ".cant_go^"; pathing = PATHING_CANT_GO; objectloop (dir in compass) { if ((~~self.(dir.door_dir) ofclass String) && (self.(dir.door_dir))()) ++ count; } if (PERSON == 3) print (The) player; else if (PERSON == 1) print "I"; else print "You"; if (count == 0) { pathing = tpath; " can't go in any direction!"; } print " can't go in that direction, but "; if (PERSON == 3) print (the) player; else if (PERSON == 1) print "I"; else print "You"; print " can move "; objectloop (dir in compass) { if ((~~self.(dir.door_dir) ofclass String) && self.(dir.door_dir)()) { if (dir == in_obj) print "in"; else if (dir == out_obj) print "out"; else print (address) dir.&name-->1; count2 ++; if (count - count2 > 1) print ", "; else if (count - count2 == 1) print " and "; } } pathing = tpath; "."; ], !map_x, map_y, region_owner nothing, region_next, has light; class MappableRoom class Room with map_x, map_y, region_owner nothing, region_next, max_x, max_y, dist [ ; return 1; ]; class Character with curwalk 0, walktime 0, isAlone [ x ; objectloop (x in RoomOf(self)) if ( (x ofclass Character || x == player) && x ~= actor) rfalse; rtrue; ], order [ naction nnoun nsecond taction tnoun tsecond tsw tval; taction = action; tsw = sw__var; tnoun = noun; tsecond = second; sw__var = action = naction; noun = nnoun; second = nsecond; tval = self.orders(); action = taction; sw__var = tsw; noun = tnoun; second = tsecond; return tval; ], startwalk [ walk ; if (walk == 0) self.curwalk = 0; else self.curwalk = self.walk; self.walktime = -1; ], stopwalk [ walk ; if (self.curwalk == self.walk) self.walk = 0; ], description [ obj numworn numheld; self.npcdesc(); objectloop (obj in self) { if (obj has worn || obj has npcworn) { give obj workflag; ++ numworn; } else { give obj ~workflag; ++ numheld; } } if (numworn > 0) { if (self ~= player || PERSON == 3) print (The) self, " is "; else if (PERSON == 1) print "I am "; else print "You are "; print "wearing "; WriteListFrom (child(self), ENGLISH_BIT | WORKFLAG_BIT | RECURSE_BIT); } if (numheld > 0) { if (numworn == 0) { if (self ~= player || PERSON == 3) print (The) self, " is"; else if (PERSON == 1) print "I am"; else print "You are"; } else print " and "; print " carrying "; objectloop (obj in self) { if (obj has worn) give obj ~workflag; else give obj workflag; } WriteListFrom (child(self), ENGLISH_BIT | WORKFLAG_BIT | RECURSE_BIT); } if (numheld > 0 || numworn > 0) "."; rtrue; ], daemon [ ; if (self.curwalk) self.curwalk(); ], first_turn [ ; StartDaemon(self); ], cansee [ obj o2; o2 = CommonAncestor(obj, self); if (o2 == 0) rfalse; while (obj ~= o2) { obj = parent(obj); if (obj ~= o2 && ~~IsSeeThrough(obj)) rfalse; } obj = self; while (obj ~= o2) { obj = parent(obj); if (obj ~= o2 && ~~IsSeeThrough(obj)) rfalse; } rtrue; ], showmove false, entertext "walks in", exittext "walks away", moveto [ destroom oldroom dir tmp t_path; oldroom = RoomOf(self); !print "(moving ", (the) self, " from ", (the) oldroom, " to ", (the) destroom, ".)"; if (oldroom == destroom) rfalse; if (self in location && self.showmove) { t_path = pathing; if (t_path) print "Huh, pathing not already 0 on entering ", (the) self, ".move_to:startroom^"; pathing = PATHING_NPC_MOVE; if (destroom) objectloop (tmp in compass) { if ((oldroom.(tmp.door_dir))() == destroom) { dir = tmp; } } !if (self.exittext) ! print (The) self, " ", (string) self.exittext; !else ! print (The) self, " walks away "; !ShowDir (dir, 0); if (self.exittext ofclass string) print (The) self, " ", (string) self.exittext, (ToDirLn) dir; !(ignore) (ShowDir (dir, 0)); else self.exittext(dir); pathing = t_path; } if (destroom) { move self to destroom; if (destroom == location && self.showmove) { t_path = pathing; if (t_path) print "Huh, pathing not already 0 on entering ", (the) self, ".move_to:destroom^"; pathing = PATHING_NPC_MOVE; if (oldroom) objectloop (tmp in compass) { if ((destroom.(tmp.door_dir))() == oldroom) { dir = tmp; } } !print (The) self, " ", (string) self.entertext; if (self.entertext ofclass string) print (The) self, " ", (string) self.entertext, (FromDirLn) dir; else self.entertext(dir); !if (self.entertext) ! print (The) self, " ", (string) self.entertext; !else ! print (The) self, " walks in "; !ShowDir (dir, 1); pathing = t_path; } } else { remove self; } ], has animate transparent; Ifdef BATTLE_SYSTEM; Constant ALIGN_ALLY 1; Constant ALIGN_NEUTRAL 2; Constant ALIGN_ENEMY 3; class Combatant class Character with max_stamina, stamina, last_attack 0, !alignment, speed, acc, agi, str, def, accuracy [ ; return randomfrom (self.&acc-->0, self.&acc-->1); ], agility [ ; return randomfrom (self.&agi-->0, self.&agi-->1); ], strength [ ; return randomfrom (self.&str-->0, self.&str-->1); ], defense [ ; return randomfrom (self.&def-->0, self.&def-->1); ], daemon [ ; ! Default behavior: Creature tries to attack first; ! if it can't, then it tries to move. if (self.find_target() == 0 && self.curwalk) self.curwalk(); ], is_enemy [ target sa ta; sa = self.alignment; ta = target.alignment; return (sa == ALIGN_ALLY && ta == ALIGN_ENEMY) || (ta == ALIGN_ALLY && sa == ALIGN_ENEMY); ], life [ ; Attack: player.strike_at(self); ], find_target [ ; if (self.last_attack + self.speed > turns) return false; objectloop (x in parent(self)) if (x ofclass Combatant && self.isEnemy(x)) ++ enemycount; !if (self in location && player notin location && ! self.isEnemy(player)) ! ++ enemycount; if (enemycount == 0) return false; enemycount = random(enemycount) objectloop (x in parent(self)) if (x ofclass Combatant && self.isEnemy(x)) { if (enemycount == 0) return self.strike_at (x); -- enemycount; } !self.strike_at(player); print_ret (The) self, " looks confused. [BUG]"; ], armor_str [ rv x; objectloop(x in self) if (x has worn || x has npcworn) rv += x.armor_str; return rv; ], choose_weapon [ wpn wstr x; if (self == player) return; objectloop (x in self) { give x ~wielded; if (x.weapon_str > wstr) { wstr = x.weapon_str; wpn = x; } } if (wpn) give wpn wielded; ], weapon_str [ rv x; objectloop(x in self) if (x has wielded) rv += x.weapon_str; return rv; ], strike_at [ target x y; self.choose_weapon(); self.last_attack = turns; x = self.accuracy(); y = target.agility(); if (x > y) { x = self.strength() + self.weapon_str(); y = target.defense() + target.armor_str(); if (x > y) target.damaged_by (self, x-y); else target.damaged_by (self, 0); } else is (self.canSee(player)) target.show_miss(self); rtrue; ], damaged_by [ attacker dmg ; self.stamina = self.stamina - dmg; if (self.stamina < 0) { StopDaemon(self); if (self.canSee(player)) self.show_death(attacker, dmg); self.on_death(); remove self; } else { if (self.canSee(player)) self.show_hit(attacker, dmg); } ], show_miss [ attacker ; print_ret (The) attacker, " swings at ", (the) self, ", but misses."; ], show_hit [ attacker dmg ; if (dmg == 0) print_ret (The) attacker, " hits ", (the) self, ", but does no damage."; print_ret (The) attacker, " hits ", (the) self, "."; ], on_death [ ; ], show_death [ attacker dmg ; print_ret (The) attacker, " kills ", (the) self, "."; ]; Endif; [ RoomOf obj; while (obj && ~~obj ofclass Room) obj = parent(obj); return obj; ]; [ FromDirLn dir; print " ", (FromDir) dir, ".^"; ]; [ ToDirLn dir; print " ", (ToDir) dir, ".^"; ]; [ FromDir dir; ShowDir(dir, 1); ]; [ ToDir dir; ShowDir(dir, 0); ]; ! if Towards is true, show messages like "from the north", ! otherwise, show messages like "to the north" [ ShowDir dir towards; switch (dir) { u_obj: if (towards) print "from above"; else print "upwards"; !print (string) towards ? " upwards" : " from above"; d_obj: if (towards) print "from below"; else print "downwards"; !print (string) (towards ? " downwards" : " from below"); in_obj: if (towards) print "from inside"; else print "inwards"; !print (string) (towards ? " inwards" : " from inside"); out_obj: if (towards) print "from outside"; else print "outwards"; !print (string) (towards ? " outwards" : " from outside"); nothing: if (towards) print "from elsewhere"; else print "away"; default: if (towards) print "from "; else print "to "; print (the) dir; !print (string) (towards ? " from " : " to "), (the) dir; } !print ".^"; ]; [ ShowRoomDesc x y; y = parent(player); PlayerTo(x); PlayerTo(y, 1); ]; Attribute npcworn; Attribute readable; Attribute sittable; Attribute lieable; class Event with time_out [ ; self.on_start(); StartDaemon(self); ], time_left -1, number -1, daemon [ ; self.time_left --; if (self.time_left <= 0) self.finish(); ], state 1, ! 1 = WAIT, 2 = RUN, 3 = AWAIT, 4 = FINISHED, 5 = PAUSED on_start [ ; ], on_finish [ ; ], !start [ ; if (self.state == 1 or 3 or 4) {self.state = 2; StartDaemon(self); self.on_start();}], start [ ; if (self.state == 1 or 3 or 4) {self.state = 2; StartTimer(self, 0); }], pause [ ; if (self.state == 2) {self.state = 5; StopDaemon(self); }], resume [ ; if (self.state == 5) {self.state = 2; StartDaemon(self); }], stop [ ; if (self.state == 2 or 4 or 5) { self.state = 3; StopDaemon(self); } ], finish [ ; StopDaemon(self); self.state = 4; self.on_finish(); ], ; Global current_style = 0; Constant S_ITAL = 1; ! Italic, changed to underline Constant S_UNITAL = 2; ! remove italic, changed to underline Constant S_BOLD = 4; ! Bold Constant S_UNBOLD = 8; ! remove bold Constant S_UNDER = 16; ! Underline Constant S_UNUNDER = 32; ! remove underline Constant S_SEC = 64; ! Secondary color Constant S_UNSEC = 128; ! primary color Constant S_LEFT = 256; ! Left justified, currently assumed Constant S_CENTER = 512; ! Centered, currently ignored Constant S_RIGHT = 1024; ! Right justified, currently ignored Constant S_JUSTIFIED = 1792; ! Left j, centered, or right j. [ Fontsize size ; if (size == -1) ! Number may be changed, but this is a "cancel size" size = 10; ! Does nothing now, but left in for glulx games ]; Default COLOR_FG 1; Default COLOR_SEC 3; Default COLOR_BG 1; [ Style type; if (type & S_ITAL) current_style = current_style | S_ITAL; else if (type & S_UNITAL) current_style = current_style & ~S_ITAL; if (type & S_BOLD) current_style = current_style | S_BOLD; else if (type & S_UNBOLD) current_style = current_style & ~S_BOLD; if (type & S_UNDER) current_style = current_style | S_UNDER; else if (type & S_UNUNDER) current_style = current_style & ~S_UNDER; if (type & S_SEC) current_style = current_style | S_SEC; else if (type & S_UNSEC) current_style = current_style & ~S_SEC; if (type & S_JUSTIFIED) current_style = current_style & ~S_JUSTIFIED; if (type & S_LEFT) current_style = current_style | S_LEFT; if (type & S_CENTER) current_style = current_style | S_CENTER; if (type & S_RIGHT) current_style = current_style | S_RIGHT; style roman; if (current_style & S_ITAL) style underline; if (current_style & S_BOLD) style bold; if (current_style & S_UNDER) style underline; if (current_style & S_SEC) @set_colour COLOR_SEC COLOR_BG; else @set_colour COLOR_FG COLOR_BG; ! Ignoring L/C/R justified ]; [ S_I str; print (Style) S_ITAL, (string) str, (Style) S_UNITAL; ]; [ S_B str; print (Style) S_BOLD, (string) str, (Style) S_UNBOLD; ]; [ S_U str; print (Style) S_UNDER, (string) str, (Style) S_UNUNDER; ]; [ WaitKey x ; @read_char 1 -> x; ]; [ randomfrom x y; return x + random(y-x); ]; ! Redundant, change to RoomOf [ RealLoc obj; while (obj && (~~ obj ofclass Room)) obj = parent(obj); return obj; ]; ! Return a random member of a particular roomgroup ! (Actually, any class, but it's meant for roomgroups) [ RandRG rg n obj; objectloop (obj ofclass rg) ++ n; n = random(n); objectloop (obj ofclass rg) { if (--n == 0) return obj; } "Fallthrough in RandRG. [BUG]^"; ]; ! Return a random room that's adjacent to 'room', and of class 'rg'. [ RandAdjRG rg room n dir t_path dest; if (~~(rg ofclass class)) "Error: RandAdjRg(", (the) rg, ", ", room, "): ", (the) rg, " not a class[BUG]"; t_path = pathing; pathing = PATHING_NPC_MOVE; if (room == nothing) room = RandRG(rg); else { objectloop (dir in compass) if ((room.(dir.door_dir)) ofclass rg) ++ n; if (n > 0) { n = random(n); objectloop (dir in compass) if ((dest = (room.(dir.door_dir))) ofclass rg) { -- n; !print "n == ", n, "; dest == ", (the) dest; if (n == 0) { room = dest; !print "; Setting room to ", (the) room, "."; break; } !print "^"; } } } pathing = t_path; return room; ]; ! Void printing rule [ ignore x ; x = x;]; [ ReadSub ; if (noun has readable) { if (noun provides readtext) noun.readtext(); else "There's nothing written on it."; } else <>; ]; [ MoveAllHeld dest obj o2; for (obj = child(player): obj: obj = o2) { o2 = sibling(obj); if (obj hasnt worn) { if (dest == nothing) remove obj; else move obj to dest; } } ]; [ MoveAllWorn dest obj o2; for (obj = child(player): obj: obj = o2) { o2 = sibling(obj); if (obj has worn) { give obj ~worn; if (dest) move obj to dest; else remove obj; } } ]; Object suppressor class Event Room Character Item with readtext "suppressor read[BUG]", npcdesc "", itemdesc "", states, state, has sittable lieable; [ WordAt wd tmp; tmp = wn; wn = wd; wd = NextWord(); wn = tmp; return wd; ]; ! Does the word at spot 'wordnum' start with the same letters as string str Array match_word_tmp->15; [ MatchWordStart wordnum str chn len; str.print_to_array(match_word_tmp); len = (match_word_tmp+0)-->0; while (++ chn < len) { if (WordAddress(wordnum)->chn ~= match_word_tmp->(chn+2)) rfalse; } rtrue; ]; [ MatchTopic w1 w2 w3 w4 w5 w6 w7 ; if (w1 == 0 || consult_words == 0) return (w1 == 0 && consult_words == 0); if (WordAt(consult_from) ~= w1) rfalse; if (w2 == 0 || consult_words == 1) return (w2 == 0 && consult_words == 1); if (WordAt(consult_from + 1) ~= w2) rfalse; if (w3 == 0 || consult_words == 2) return (w3 == 0 && consult_words == 2); if (WordAt(consult_from + 2) ~= w3) rfalse; if (w4 == 0 || consult_words == 3) return (w4 == 0 && consult_words == 3); if (WordAt(consult_from + 3) ~= w4) rfalse; if (w5 == 0 || consult_words == 4) return (w5 == 0 && consult_words == 4); if (WordAt(consult_from + 4) ~= w5) rfalse; if (w6 == 0 || consult_words == 5) return (w6 == 0 && consult_words == 5); if (WordAt(consult_from + 5) ~= w6) rfalse; if (w7 == 0 || consult_words == 6) return (w7 == 0 && consult_words == 6); if (WordAt(consult_from + 6) ~= w7) rfalse; rtrue; ]; [ Suppress ; MoveAllHeld (); s_bold(); s_ital(); s_unbold(); s_unital(); randomfrom(); DeathMessage(); Suppress(); print npcworn; ShowRoomDesc(); ignore(); ObjState(); Wornby(); Fontsize(); Style(); RealLoc(); RandRG(); ReadSub(P_Sitting + P_Standing + P_Lying + W_VLight + W_Light + W_Normal + W_Heavy + W_VHeavy + !S_Tiny + S_Small + S_Normal + S_Large + S_Huge + 0); WaitKey(); MatchTopic(); MoveAllWorn(); PromptForName(); !CallSilently(); S_I(); S_B(); S_U(); MatchWordStart(); ]; Ifdef AUTOMAP; Ifndef MAP_WIDTH; Constant MAP_WIDTH 20; endif; Ifndef MAP_HEIGHT; Constant MAP_HEIGHT 13; endif; Array Automap_Chars -> (MAP_HEIGHT * MAP_WIDTH); Constant MAP_ABSENT 0; Constant MAP_ZOOMED_IN 1; Constant MAP_ZOOMED_OUT 2; Global map_zoom = MAP_ZOOMED_IN; !Global graphic_mode; Verb meta 'zoom' * 'in' -> ZoomIn * 'out' -> ZoomOut * 'away'/'absent' -> ZoomAway * -> Zoom; [ ZoomInSub ; map_zoom = MAP_ZOOMED_IN; "Zooming in."; ]; [ ZoomOutSub ; map_zoom = MAP_ZOOMED_OUT; "Zooming out."; ]; [ ZoomAwaySub ; map_zoom = MAP_ABSENT; "Removing map."; ]; [ ZoomSub ; if (map_zoom == MAP_ZOOMED_IN) <>; if (map_zoom == MAP_ZOOMED_OUT) <>; if (map_zoom == MAP_ABSENT) <>; "Bad value ", map_zoom, " for map_zoom.[BUG]"; ]; Ifndef CustomStatusLine; ! Minor variation on std lib [ DrawStatusLine width posa posb ctr drew_map ch graphic_mode; ! Put this before @split_window, so errors go low. !if (map_zoom ~= MAP_ABSENT) drew_map = DrawMap(location); !else !drew_map = false; !@set_font 3 -> posa; !print "Set font returned ", posa, "^"; !@set_font 1 -> posa; !print "Set font returned ", posa, "^"; style reverse; posa = MAP_HEIGHT + 1; if (drew_map) @split_window posa; else if (map_zoom ~= ZOOM_AWAY) @split_window 2; else @split_window 1; @set_window 1; #Ifdef TARGET_GLULX; ! If we have no status window, we must not try to redraw it. if (gg_statuswin == 0) return; #Endif; if (location == nothing || parent(player) == nothing) return; StatusLineHeight (gg_statuswin_size); MoveCursor(1, 1); width = ScreenWidth(); posa = width - 26; posb = width - 13; spaces width; MoveCursor (1, 2); if (location == thedark) print (name) location; else { FindVisibilityLevels(); if (visibility_ceiling == location) print (name) location; else print (The) visibility_ceiling; } if (sys_statusline_flag && width > 53) { MoveCursor(1, posa); print (string) TIME__TX; LanguageTimeOfDay(sline1, sline2); } else { if (width > 66) { #Ifndef NO_SCORE; MoveCursor(1, posa); print (string) SCORE__TX, sline1; #Endif; MoveCursor(1, posb); print (string) MOVES__TX, sline2; } #Ifndef NO_SCORE; if (width > 53 && width <= 66) { MoveCursor(1, posb); print sline1, "/", sline2; } #Endif; } ! Now for stuff custom to the automapper if (drew_map) { style roman; font off; !! Following line is commented out temporarily @set_font 3 -> graphic_mode; graphic_mode = 0; if (graphic_mode == 0) { for (ctr = 0: ctr < MAP_HEIGHT * MAP_WIDTH: ctr ++) { ch = Automap_Chars->ctr; if (ch ~= 32) { if (ch == 35 or 50 or 52) ch = '/'; else if (ch == 36 or 51 or 53) ch = '\'; !else if (ch == 40 or 41) ch = '|'; !else if (ch == 38 or 39) ch = '-'; !else if (ch == 91 or 42 or 43 or 44 or 45) ch = '+'; else if (ch == 40 or 41) ch = '|'; else if (ch == 38 or 39) ch = '-'; else if (ch == 91 or 42 or 43 or 44 or 45) ch = '+'; else if (ch >= 54 && ch <= 70) ch = '*'; else if (ch == 37) ch = ' '; else if (ch >= 37 && ch <= 53 || ch == 95) ch = 'o'; else if (ch == 90) ch = 'X'; else if (ch == 92 or 123) ch = 'U'; else if (ch == 93 or 124) ch = 'D'; else if (ch == 94 or 125) ch = ';'; else if (ch == 96 or 126) ch = '?'; else if (ch == 2) ch = '|'; else if (ch == 1) ch = '-'; else { @set_window 0; print "Bad number ", ch, " in map."; @set_window 1; ch = '?'; } Automap_Chars -> ctr = ch; } } } else for (ctr = 0: ctr < MAP_HEIGHT * MAP_WIDTH: ctr ++) { ch = Automap_Chars->ctr; if (ch == 1) Automap_Chars->ctr = 38; else if (ch == 2) Automap_Chars->ctr = 40; } ctr = 0; for (posa = 2: posa <= MAP_HEIGHT + 1: posa ++) { posb = width - MAP_WIDTH + 1; @set_cursor posa posb; for (posb = 0: posb < MAP_WIDTH: posb ++) print (char) Automap_Chars->(ctr++); } @set_font 1 -> posa; } else if (map_zoom ~= MAP_ABSENT) { @set_cursor 2 1; spaces (width - 23) / 2; print "(automap not available)"; spaces (width - 24) / 2; } @set_cursor 1 1; style roman; @set_window 0; font on; @split_window 1; !MainWindow(); ! set_window ]; endif; [ MapExitValid room dir dest; dest = room.(dir.door_dir); if (dest == nothing || dest ofclass String) rfalse; dest = room.(dir.door_dir)(); if (dest == 0 || (~~dest ofclass MappableRoom)) rfalse; return dest; ]; !Global map_min_x; !Global map_min_y; Global room_size; [ min x y; if (x < y) return x; return y; ]; [ max x y; if (x < y) return y; return x; ]; [ DrawPath sq_x sq_y dx dy dist ch sq ch2; dist = (dist - 1) * room_size + 1; sq_x = sq_x + dx; sq_y = sq_y + dy; while (sq_x >= 0 && sq_x < MAP_WIDTH && sq_y >= 0 && sq_y < MAP_HEIGHT && dist > 0) { sq = sq_y * MAP_WIDTH + sq_x; ch2 = Automap_Chars->sq; if (ch2 == ' ') Automap_Chars->sq = ch; else if (ch2 == ch or 90 or 91) ; else if (ch == 35 or 36) Automap_Chars->sq = 90; !else if (ch == 38 or 39 or 40 or 41) else if (ch == 1 or 2) Automap_Chars->sq = 91; else print "Draw Path got bad value with ", ch, " over ", ch2, "[BUG]^"; dist --; sq_x = sq_x + dx; sq_y = sq_y + dy; } ]; [ PlaceCharAt x y ch; !print "PCA(", x, ", ", y, ", ", ch, ")^"; if (x >= 0 && x < MAP_WIDTH && y >= 0 && y < MAP_HEIGHT) Automap_Chars->(y*MAP_WIDTH + x) = ch; ]; [ DrawMap room tmp_path i region tmp_x tmp_y offset obj map_min_x map_min_y; if (~~room ofclass MappableRoom) rfalse; tmp_path = pathing; pathing = PATHING_MAP_PLACING; if (tmp_path) print "Huh, pathing not already 0 on entering DrawMap(", (the) room, ")^"; ExploreRoom(room); if (map_zoom == MAP_ABSENT) { pathing = tmp_path; rfalse; } pathing = PATHING_MAP_DRAWING; !print "Showing mapped for DrawMap^"; !ShowMappedRegion(); !rtrue; !print "room == ", room, "; region == ", room.region_owner, ".^"; region = room.region_owner; !room_size = (map_zoom == MAP_ZOOMED_IN) ? 4 : 2; if (map_zoom == MAP_ZOOMED_IN) room_size = 4; else room_size = 2; !print "region == ", (the) region, ".^"; !print "Logical region is (0 - ", region.max_x, ")x(0 - ", region.max_y, "), corresponding to (0 - ", region.max_x * room_size, ")x(0 - ", region.max_y * room_size, ")^"; !!! max (wmost, min (center - WIDTH/2, emost - WIDTH)) if (2 + room_size * (1+region.max_x) >= MAP_WIDTH) map_min_x = max(-2, min (2 + (1+room.map_x) * room_size - MAP_WIDTH/2, (1+region.max_x) * room_size - MAP_WIDTH)); else map_min_x = (room_size * (1+region.max_x) - MAP_WIDTH) / 2; !print "Height #s ", 2 + room_size * (1+region.max_y), " vs. ", MAP_HEIGHT, ! "; ", -2, ", ", region.max_y * room_size - MAP_HEIGHT, ", ", ! 2 + room_size * room.map_y - (MAP_HEIGHT/2), "; ", ! ((1+room_size) * region.max_y - MAP_HEIGHT) / 2, " -> "; !!! max (nmost, min (center - WIDTH/2, smost - WIDTH)) if (2 + room_size * (1+region.max_y) >= MAP_HEIGHT) map_min_y = max(-2, min (2 + room_size * (1+room.map_y) - MAP_HEIGHT/2, (1+region.max_y) * room_size - MAP_HEIGHT)); else map_min_y = (room_size * (1+region.max_y) - MAP_HEIGHT) / 2; !print "", map_min_y, "^"; !print "Mapped region is (", map_min_x, " - ", map_min_x + MAP_WIDTH, ") x (", map_min_y, " - ", map_min_y + MAP_HEIGHT, ")^"; for (i = 0: i < MAP_HEIGHT * MAP_WIDTH: i ++) Automap_Chars -> i = ' '; for (obj = region: obj: obj = obj.region_next) { !print " Handling ", (the) obj, " from ", (the) region, " towards (", obj.map_x, ", ", obj.map_y, ") "; tmp_x = obj.map_x * room_size - map_min_x; tmp_y = obj.map_y * room_size - map_min_y; !print " To place at (", tmp_x, ", ", tmp_y, ")^"; if (tmp_x + room_size < 0 || tmp_x >= MAP_WIDTH || tmp_y + room_size < 0 || tmp_y >= MAP_HEIGHT) { !print " Room out of range^"; continue; } if (map_zoom == MAP_ZOOMED_IN) { !offset = (obj == room) ? 54 : 37; if (obj == room) offset = 54; else offset = 37; if (MapExitValid(obj, sw_obj)) { PlaceCharAt (tmp_x, tmp_y + 2, offset + 13); DrawPath (tmp_x, tmp_y + 2, -1, 1, obj.dist(sw_obj), 35); } else PlaceCharAt (tmp_x, tmp_y + 2, offset + 9); if (MapExitValid(obj, nw_obj)) { PlaceCharAt (tmp_x, tmp_y, offset + 14); DrawPath (tmp_x, tmp_y, -1, -1, obj.dist(nw_obj), 36); } else PlaceCharAt (tmp_x, tmp_y, offset + 10); if (MapExitValid(obj, ne_obj)) { PlaceCharAt (tmp_x + 2, tmp_y, offset + 15); DrawPath (tmp_x + 2, tmp_y, 1, -1, obj.dist(ne_obj), 35); } else PlaceCharAt (tmp_x + 2, tmp_y, offset + 11); if (MapExitValid(obj, se_obj)) { PlaceCharAt (tmp_x + 2, tmp_y + 2, offset + 16); DrawPath (tmp_x + 2, tmp_y + 2, 1, 1, obj.dist(se_obj), 36); } else PlaceCharAt (tmp_x + 2, tmp_y + 2, offset + 12); if (MapExitValid (obj, n_obj)) { PlaceCharAt (tmp_x + 1, tmp_y, offset + 5); DrawPath (tmp_x + 1, tmp_y, 0, -1, obj.dist(n_obj), 40); } else PlaceCharAt (tmp_x + 1, tmp_y, offset + 2); if (MapExitValid (obj, s_obj)) { PlaceCharAt (tmp_x + 1, tmp_y + 2, offset + 6); DrawPath (tmp_x + 1, tmp_y + 2, 0, 1, obj.dist(n_obj), 40); } else PlaceCharAt (tmp_x + 1, tmp_y + 2, offset + 1); if (MapExitValid (obj, e_obj)) { PlaceCharAt (tmp_x + 2, tmp_y + 1, offset + 7); DrawPath (tmp_x + 2, tmp_y + 1, 1, 0, obj.dist(n_obj), 38); } else PlaceCharAt (tmp_x + 2, tmp_y + 1, offset + 3); if (MapExitValid (obj, w_obj)) { PlaceCharAt (tmp_x, tmp_y + 1, offset + 8); DrawPath (tmp_x, tmp_y + 1, -1, 0, obj.dist(n_obj), 38); } else PlaceCharAt (tmp_x, tmp_y + 1, offset + 4); PlaceCharAt (tmp_x + 1, tmp_y + 1, offset); !offset = (room == obj) ? 123 : 92; if (room == obj) offset = 123; else offset = 92; if (MapExitValid (obj, u_obj) && MapExitValid (obj, d_obj)) PlaceCharAt (tmp_x + 1, tmp_y + 1, offset + 2); else if (MapExitValid (obj, u_obj)) PlaceCharAt (tmp_x + 1, tmp_y + 1, offset); else if (MapExitValid (obj, d_obj)) PlaceCharAt (tmp_x + 1, tmp_y + 1, offset + 1); else if (MapExitValid (obj, in_obj) || MapExitValid (obj, out_obj)) PlaceCharAt (tmp_x + 1, tmp_y + 1, offset + 3 + (room ~= obj)); } else { if (MapExitValid (obj, sw_obj)) DrawPath(tmp_x, tmp_y, -1, 1, obj.dist(nw_obj), 35); if (MapExitValid (obj, nw_obj)) DrawPath(tmp_x, tmp_y, -1, -1, obj.dist(nw_obj), 36); if (MapExitValid (obj, ne_obj)) DrawPath(tmp_x, tmp_y, 1, -1, obj.dist(nw_obj), 35); if (MapExitValid (obj, se_obj)) DrawPath(tmp_x, tmp_y, 1, 1, obj.dist(nw_obj), 36); if (MapExitValid (obj, n_obj)) DrawPath(tmp_x, tmp_y, 0, -1, obj.dist(n_obj), 2); if (MapExitValid (obj, s_obj)) DrawPath(tmp_x, tmp_y, 0, 1, obj.dist(s_obj), 2); if (MapExitValid (obj, e_obj)) DrawPath(tmp_x, tmp_y, 1, 0, obj.dist(e_obj), 1); if (MapExitValid (obj, w_obj)) DrawPath(tmp_x, tmp_y, -1, 0, obj.dist(w_obj), 1); !if (obj == room) ! PlaceCharAt (tmp_x, tmp_y, 54); !else ! PlaceCharAt (tmp_x, tmp_y, 95); !PlaceCharAt (tmp_x + 1, tmp_y + 1, offset); !offset = (room == obj) ? 123 : 92; if (room == obj) offset = 123; else offset = 92; if (MapExitValid (obj, u_obj) && MapExitValid (obj, d_obj)) PlaceCharAt (tmp_x, tmp_y, offset + 2); else if (MapExitValid (obj, u_obj)) PlaceCharAt (tmp_x, tmp_y, offset); else if (MapExitValid (obj, d_obj)) PlaceCharAt (tmp_x, tmp_y, offset + 1); else if (MapExitValid (obj, in_obj) || MapExitValid (obj, out_obj)) PlaceCharAt (tmp_x, tmp_y, offset + 3 + (room ~= obj)); else if (room == obj) PlaceCharAt (tmp_x, tmp_y, 54); else PlaceCharAt (tmp_x, tmp_y, 95); } } pathing = tmp_path; if (0) { UnmapRoom(0); print "["; for (tmp_x = 0: tmp_x < MAP_WIDTH * MAP_HEIGHT: tmp_x ++) { if (tmp_x % MAP_WIDTH == 0) print "^"; if (Automap_chars->tmp_x == 32) print ".. "; else print Automap_Chars->tmp_x, ", "; } print "]^"; } !DisplayMapLow(); rtrue; ]; ![ DisplayMapLow tmp_x tmp_y; ! print "^+"; ! for (tmp_x = 0: tmp_x < MAP_WIDTH: tmp_x ++) ! print "-"; ! print "+^"; ! for (tmp_y = 0: tmp_y < MAP_HEIGHT: tmp_y ++) { ! print "|"; ! for (tmp_x = 0: tmp_x < MAP_WIDTH: tmp_x ++) ! print (char) Automap_chars->(tmp_y*MAP_WIDTH + tmp_x); ! print "|^"; ! } ! print "+"; ! for (tmp_x = 0: tmp_x < MAP_WIDTH: tmp_x ++) ! print "-"; ! print "+^"; !]; ! Set up region so that: ! Minimum x value within that region == 0 ! Maximum x value within that region == region_owner.max_x ! Similar with y [ RecenterRegion room min_xx max_xx min_yy max_yy obj; !print " [RecenterRegion ", (the) room, "]^"; !print "Before recentering^"; !ShowMappedRegion(); min_xx = max_xx = room.map_x; min_yy = max_yy = room.map_y; for (obj = room.region_owner: obj: obj = obj.region_next) { !print " looking at ", (the) obj, "[", obj.map_x, ", ", obj.map_y, "]^"; if (obj.map_x < min_xx) min_xx = obj.map_x; else if (obj.map_x > max_xx) max_xx = obj.map_x; if (obj.map_y < min_yy) min_yy = obj.map_y; else if (obj.map_y > max_yy) max_yy = obj.map_y; } !print " After loop, range is (", min_xx, "-", max_xx, ") x (", min_yy, "-", max_yy, ")^"; if (min_xx ~= 0) for (obj = room: obj: obj = obj.region_next) { !print "Recenter setting ", (name) obj, ".x := ", obj.map_x - min_xx, "^"; obj.map_x = obj.map_x - min_xx; } if (min_yy ~= 0) for (obj = room: obj: obj = obj.region_next) { !print "Recenter setting ", (name) obj, ".y := ", obj.map_y - min_yy, "^"; obj.map_y = obj.map_y - min_yy; } !print " Renormalized numbers^"; room.max_x = max_xx - min_xx; room.max_y = max_yy - min_yy; !print " Returning from RecenterRegion^"; !print "After recentering^"; !ShowMappedRegion(); ]; ! Remove 'room' from all regions [ UnmapRoom room newval obj; if (room.region_owner == room) { newval = room.region_next; for (obj = newval: obj.region_next: obj = obj.region_next) obj.region_owner = newval; } else if (room.region_owner) { for (obj = room.region_owner: obj.region_next ~= room: obj = obj.region_next) ; obj.region_next = room.region_next; RecenterRegion(room.region_owner); } room.region_owner = nothing; room.region_next = nothing; ]; [ DirChangesRegion dir; return dir == u_obj or d_obj or in_obj or out_obj; ]; [ DirChangeX dir; if (dir == nw_obj or w_obj or sw_obj) return -1; if (dir == ne_obj or e_obj or se_obj) return 1; return 0; ]; [ DirChangeY dir; if (dir == nw_obj or n_obj or ne_obj) return -1; if (dir == sw_obj or s_obj or se_obj) return 1; return 0; ]; ![ ShowMappedRegion dest; ! objectloop (dest ofclass MappableRoom) { ! if (dest.region_owner == nothing) continue; ! print " ", (the) dest, ": ", (the) dest.region_owner, " / ", ! (the) dest.region_next, "a(", dest.map_x, ", ", dest.map_y, ")^"; ! } ! print "Done printing current map.^"; !]; ! Is a path from 'oroom' heading 'dir' to 'nroom' consistent with the ! current automap, and, if necessary, make such a connection. [ CheckConn nroom oroom dir; !print " [CheckConn (",(the) nroom, ") (",(the) oroom, ") (",(the) dir,")]^"; if (DirChangesRegion(dir)) rtrue; if (nroom.region_owner == nothing) rtrue; if (nroom.region_owner ~= oroom.region_owner) { JoinRegions (nroom, oroom, dir); !print " returning from CheckConn^"; rtrue; } !print " -> ", oroom.map_x + oroom.dist(dir) * DirChangeX(dir), " == ", nroom.map_x, ", ", oroom.map_y + oroom.dist(dir) * DirChangeY(dir), " == ", nroom.map_y, " -> ", (oroom.map_x + oroom.dist(dir) * DirChangeX(dir) == nroom.map_x && oroom.map_y + oroom.dist(dir) * DirChangeY(dir) == nroom.map_y), "^"; return (oroom.map_x + oroom.dist(dir) * DirChangeX(dir) == nroom.map_x && oroom.map_y + oroom.dist(dir) * DirChangeY(dir) == nroom.map_y); ]; [ JoinRegions nroom oroom dir ddx ddy newx newy obj; !print " [JoinRegions (",(the) nroom,") (",(the) oroom,") (",(the) dir,")]^"; newx = oroom.map_x + oroom.dist(dir) * DirChangeX(dir); newy = oroom.map_y + oroom.dist(dir) * DirChangeY(dir); if (nroom.region_owner == nothing) { !print " nroom not in a region^"; ! Set values for nroom print "JoinRegions a: ", (name) nroom, " := (", newx, ", ", newy, ")^"; nroom.map_x = newx; nroom.map_y = newy; nroom.region_owner = oroom.region_owner; nroom.region_next = nothing; !print " Set nroom's values^"; ! Find last room in old group for (obj = oroom: obj.region_next: obj = obj.region_next) ; ! And set its region_next !print " Setting obj.region_next: ", (the) obj, "^"; obj.region_next = nroom; !for (obj = obj.region_next: obj: obj = obj.region_next) ! obj.region_owner = oroom.region_owner; } else { !print " nroom in a region (", (the) nroom.region_owner, ")^"; ! Set obj to last room in old region for (obj = oroom: obj.region_next: obj = obj.region_next) ; obj.region_next = nroom.region_owner; ! Add new region to old region ddx = nroom.map_x - newx; ddy = nroom.map_y - newy; ! Set offsets ! For each room in new region, update owner & coordinates !print "Setting map_x in JoinRegions b^"; for (obj = nroom.region_owner: obj: obj = obj.region_next) { obj.region_owner = oroom.region_owner; !print "Join regions b setting ", (name) obj, ":= (", obj.map_x, ", ", obj.map_y, ")^"; obj.map_x = obj.map_x - ddx; obj.map_y = obj.map_y - ddy; } } !print " Recentering^"; RecenterRegion(nroom.region_owner); !print " Returning from Join regions^"; ]; ! Make sure that each adjacent known room in a region-preserving direction, ! is in the same region, and has consistent map_x, map_y values ! ! (directions that preserve region are n,ne,e,se,s,sw,w,nw; ! directions that don't are in, out, up, down) [ ExploreRoom room dest dir; if (~~room ofclass MappableRoom) rtrue; !tmp_path = pathing; !pathing = room; if (room.region_owner == nothing) { room.region_owner = room; !print "Presetting x,y in ExploreRoom^"; room.map_y = 0; room.map_x = 0; room.region_next = nothing; } objectloop (dir in compass) { dest = room.(dir.door_dir)(); if (dest == 0 or 1 || (~~dest ofclass MappableRoom) || DirChangesRegion(dir)) continue; if (~~CheckConn (dest, room, dir)) print "Error connecting ", (the) room, " to ", (the) dir, " to ", (the) dest, "[BUG].^"; } !pathing = tmp_path; ]; Endif; !!!!! ! ! LIBRARY REPLACEMENTS ! !!!!! Ifdef USE_SIZES; [ WeightOf obj x rv; rv = obj.weight; objectloop(x in obj) rv = rv + WeightOf(x); return rv; ]; [ UsedSize obj x rv; objectloop(x in obj) rv = rv + x.size; return rv; ]; [ InsertSub ancestor; receive_action = ##Insert; if (second == d_obj || player in second) <>; if (parent(noun) == second) return L__M(##Drop,1,noun); if (parent(noun) ~= player) return L__M(##Insert, 1, noun); ancestor = CommonAncestor(noun, second); if (ancestor == noun) return L__M(##Insert, 5, noun); if (ObjectIsUntouchable(second)) return; if (second ~= ancestor) { action = ##Receive; if (RunRoutines(second,before) ~= 0) { action = ##Insert; rtrue; } action = ##Insert; if (second has container && second hasnt open) return L__M(##Insert, 3, second); } if (second hasnt container) return L__M(##Insert, 2, second); if (noun has worn) { L__M(##Insert, 6, noun); ; if (noun has worn) return; } ! ValueOrRun changed to simple dereference because this can use ! large values !if (children(second) >= ValueOrRun(second, capacity)) if (UsedSize(second) + noun.size > second.capacity) ! Changed MJT return L__M(##Insert, 7, second); move noun to second; if (AfterRoutines() == 1) rtrue; if (second ~= ancestor) { action = ##Receive; if (RunRoutines(second, after) ~= 0) { action = ##Insert; rtrue; } action = ##Insert; } if (keep_silent == 1) rtrue; if (multiflag == 1) return L__M(##Insert, 8, noun); L__M(##Insert, 9, noun); ]; [ AttemptToTakeObject item ancestor after_recipient i j k sz; ! Try to transfer the given item to the player: return false ! if successful, true if unsuccessful, printing a suitable message ! in the latter case. ! People cannot ordinarily be taken. if (item == player) return L__M(##Take, 2); if (item has animate) return L__M(##Take, 3, item); ancestor = CommonAncestor(player, item); if (ancestor == 0) { i = ObjectScopedBySomething(item); if (i ~= 0) ancestor = CommonAncestor(player, i); } ! Is the player indirectly inside the item? if (ancestor == item) return L__M(##Take, 4, item); ! Does the player already directly contain the item? if (item in player) return L__M(##Take, 5, item); ! Can the player touch the item, or is there (e.g.) a closed container ! in the way? if (ObjectIsUntouchable(item, false, true)) return; ! The item is now known to be accessible. ! Consult the immediate possessor of the item, if it's in a container ! which the player is not in. i = parent(item); if (i && i ~= ancestor && (i has container || i has supporter)) { after_recipient = i; k = action; action = ##LetGo; if (RunRoutines(i, before) ~= 0) { action = k; rtrue; } action=k; } if (item has scenery) return L__M(##Take, 10, item); if (item has static) return L__M(##Take, 11, item); ! The item is now known to be available for taking. Is the player ! carrying too much? If so, possibly juggle items into the rucksack ! to make room. ! Changes below for ADRIFT capacity - MJT sz = 0; objectloop (j in player) if (j hasnt worn) sz = sz + WeightOf(j); if (sz + noun.weight > player.max_wt) "That's too heavy."; sz = 0; objectloop (j in player) if (j hasnt worn) sz = sz + j.size; !if (k >= ValueOrRun(player, capacity)) { while (sz + noun.size > player.max_size) { ! MJT if (SACK_OBJECT ~= 0) { if (parent(SACK_OBJECT) ~= player) return L__M(##Take, 12); j = 0; objectloop (k in player) if (k ~= SACK_OBJECT && k hasnt worn && k hasnt light) j = k; if (j ~= 0) { L__M(##Take, 13, j); keep_silent = 1; ; keep_silent = 0; if (j notin SACK_OBJECT) rtrue; sz = sz - j.size; } else return L__M(##Take, 12); } else return L__M(##Take, 12); } ! Transfer the item. move item to player; ! Send "after" message to the object letting go of the item, if any. if (after_recipient ~= 0) { k = action; action = ##LetGo; if (RunRoutines(after_recipient, after) ~= 0) { action = k; rtrue; } action=k; } rfalse; ]; Endif;