= Advanced Building When you really want to get creative. This page collects the deeper builder tools — the ones that turn rooms and items from scenery into //things players do//. Everything here needs a builder role (**worldbuilder**, **implementor**, or **admin**), and builds on the basics in **[[How to Build]]**, **[[All about Items]]**, and **[[All about Mobiles]]**. == Puzzles: hidden things, locks, and secret ways With a handful of data fields an item stops being mere gear and becomes an **interactive prop**: something you disturb, a lock you open with the right key, a secret way that appears. There's no scripting -- each behaviour is one flat **data** field (set with **item //ref// data //field// //value//**), so a puzzle is content you build in-game, not code. === Invisible items **data invisible true** -- the item is present and you can still refer to it by keyword (**look**/**move**/**take** it //if you know the word//), but it is **not listed** when you look at the room. Use it for a prop the room's own description already hints at (so it isn't named twice), or for something that stays hidden until it's revealed. Usually paired with **data fixed true** so it can't be pocketed. === Searchable objects -- found with **search** **data searchable true** -- a player who types **search** in the room turns this item up. Pair it with **data invisible true** and the item is unlisted until someone searches; on a find its //invisible// flag is cleared, so it then shows for everyone (a lever you uncover stays uncovered). A bare **search** only reveals //searchable// items -- an invisible prop that isn't searchable (a grate under leaves, uncovered by its own trigger) is left alone, so searching never shortcuts a puzzle. **search //item//** is still free for a **verb_search** flavour hook. Searching a pitch-black room you have no light for finds nothing. === Verb hooks -- things you can do to a prop Give an item a custom action with **data verb_//word// //message//**: when a player types "//word// //item//", the message prints. * e.g. **data verb_move**, **verb_pull**, **verb_push**, **verb_count**, **verb_search**, **verb_turn**, **verb_rub** ... * Add **data verb_//word//_reveal //keyword//** to make that action **reveal** a hidden sibling item in the same room (it clears that item's //invisible// flag) -- a one-way uncover. * Or **data verb_//word//_toggle //keyword//** to //flip// that sibling hidden <-> shown each time -- leaves you sweep off a grate and rake back over it. Handy so a puzzle resets itself (nothing is ever permanently uncovered for everyone). * Add **data verb_//word//_exit //dir//** to open a **hidden exit** (see below) out of the room: the action clears that direction's **hidden_//dir//** flag, so a wall slides back and the passage becomes walkable -- e.g. a lever with **verb_pull_exit west**. * **take**/**get** are hookable too (**data verb_take //message//**), so a fixed prop can //react// to being taken instead of just refusing. * //A few interaction words are also ordinary commands.// **look** and **read** always show an item's description (use those for readable props); the interaction verbs above are free. === Locks and keys * **data lock //lockword//** -- the item has a lock identified by that word (any word you pick). * **data locked true** -- it starts locked. * On the **key** item: **data key //lockword//** -- a key //held in hand// whose word matches opens it. Players use **unlock //item//** and **lock //item//**; unlocking needs the matching key on them. === Openables and state descriptions * **data openable true** + **data open false** -- players **open //item//** / **close //item//**. Opening is refused while it's **locked**. * **data ground_closed //line//** and **data ground_open //line//** -- the sentence the item adds to the room description, chosen by whether it's open. (Plain **data ground //line//** is the fallback for a prop with no open/closed state.) === Secret ways -- object exits An open prop can be a way out of the room: * **data exit_to //room#//** -- where it leads. * **data exit_verbs //phrases//** -- the trigger phrases, separated by **commas** (e.g. **down, enter cellar**); type any one, while the prop is open, to go through. The commas are REQUIRED: a single phrase may contain spaces ("enter cellar" is one phrase, not two), so a space-separated list like "down enter cellar" is read as ONE long phrase and will match nothing a player would actually type. * optional flavour: **data exit_self //what you see//**, **data exit_leave //what this room sees//**, **data exit_arrive //what the far room sees//**. An **openable** exit only works once it's open; a prop with no open/closed state is always live. === Hidden exits -- secret passages on the room A room's own **[[How to Build|cardinal exits]]** can be **hidden**: a passage that isn't listed and can't be walked until something opens it. Set it on the room (not an item): * **room data hidden_//dir//** -- e.g. **hidden_west**, **hidden_up**. That exit vanishes from **exits** and won't let anyone through (it reads exactly like a wall), even though the exit destination is still wired. * An item's **verb_//word//_exit //dir//** hook clears the flag and opens it for good -- so pulling a lever, turning a stone, or speaking a word slides the passage open. Because a hidden exit is unwalkable until opened, **search** deliberately does //not// disclose it -- players find the mechanism (the lever), not the door. To move a room between hidden and open yourself, just set or clear **hidden_//dir//**. (A builder can always **goto** past it.) === Secret exits -- read-the-room passages Sometimes you want no mechanism at all: the exit should simply be //unlisted//, and a player who reads the room and takes the hint can just walk it. That is a **secret** exit -- the lighter cousin of a hidden one, where the //reading// is the whole puzzle. Set it on the room (not an item): * **room data secret_//dir//** -- e.g. **secret_south**, **secret_west**. The exit vanishes from **exits** and autoexits, but stays fully **walkable**: anyone who types that direction walks straight through. Nothing opens it and nothing needs to -- it was never sealed, only unlisted. * The room's own description is the //only// signpost, so write the clue into the prose (//"a draft slides up from somewhere low in the southern web..."//) and let the player find the way by reading and trying it. * Set or clear it like any flag (**room data secret_west true** / **secret_west false**). For a two-way secret passage, set the matching flag at each end -- **secret_west** in this room, **secret_east** in the one it joins. Contrast with **hidden_//dir//** above: //hidden// is a **sealed wall** that needs a lever or gate to open; //secret// is an **open doorway you simply can't see listed**. Reach for **secret_//dir//** when the challenge is //noticing the clue//, and **hidden_//dir//** when it's //working a mechanism//. === A worked example: a rug, a trapdoor, a cellar {{{ (in a room whose description already mentions a threadbare rug on the floor) item create rug item rug data invisible true (the desc mentions it; don't list it twice) item rug data fixed true item rug data keywords rug carpet item rug data verb_move A trapdoor is revealed beneath the rug! item rug data verb_move_reveal trapdoor item create trapdoor item trapdoor data invisible true (hidden until the rug is moved) item trapdoor data fixed true item trapdoor data keywords trapdoor door hatch item trapdoor data lock cellarhatch item trapdoor data locked true item trapdoor data openable true item trapdoor data ground_closed A heavy trapdoor is set into the floor, locked. item trapdoor data ground_open An open trapdoor gapes, its stairs sinking into the dark. item trapdoor data exit_to 57 (the cellar's room number) item trapdoor data exit_verbs down, enter cellar (and the key, waiting somewhere in the world) item create iron key item iron data key cellarhatch }}} Now a player who **move**s the rug reveals the trapdoor; **unlock trapdoor** (with the iron key in hand), **open trapdoor**, then **down** (or **enter cellar**) drops them into room 57. Extra **verb_** hooks -- a **count**, a **search** -- add flavour. Combine the same pieces for levers, hidden doors, sealed chests, and more. === A second example: a hidden lever opens a secret wall A **search**-and-**pull** puzzle: the room has a real west exit, but it's sealed until you find and pull a concealed lever. {{{ (standing in the room, whose west exit already leads somewhere) room data hidden_west true (the west passage is sealed and unlisted) item create lever item lever name hidden lever item lever data invisible true (not listed...) item lever data searchable true (...until someone searches) item lever data fixed true item lever data verb_pull You pull the lever and a passage opens up in the west wall! item lever data verb_pull_exit west (pulling clears hidden_west -> the way opens) drop lever }}} A player who **search**es the room finds the lever; **pull lever** prints the line and opens the west passage (for everyone) so they can walk **west**. Until then, **exits** never mentions it and **west** just says you can't go that way. == Timed events -- gates and doors on the game clock An object can open and close on its own, by the hour of the [[How to Play|game clock]] -- the classic town gate that opens at dawn and bars the road at nightfall. It reuses the **openable** and **object-exit** machinery above; you just add a schedule (and, if you like, two announcements): * **data open_at //hour//** -- the hour (0-23) it opens. 5 is the crack of dawn (the sun begins to rise); 6 is full daylight. * **data close_at //hour//** -- the hour (0-23) it closes. 20 is the sun's final setting (nightfall). * **data open_msg //line//** -- announced in the object's room when it opens (optional; a plain default is used if unset). * **data close_msg //line//** -- announced in the object's room when it closes (optional). The clock's hourly tick flips the object's **open** flag on schedule and prints the message to its room. A daemon restart snaps every timed object to whatever its schedule implies for the current hour, so a gate is never caught mid-cycle. Because it's a normal **openable**, a shut gate refuses passage through its **exit_to** (//"The town gate is closed."//), and a timed object can't be worked by hand -- **open** / **close** are refused, since it keeps to its own clock. Two things worth knowing: the window may wrap past midnight (**open_at 20** + **close_at 6** is a gate open //only// through the night); and you almost always want **data fixed true** (so it can't be picked up) plus **ground_open** / **ground_closed** lines (so the room shows its current state). === A worked example: the Eastern Gate A gate wants a face on //both// sides, so it's two "town gate" objects -- one in each room the gate stands between -- each leading through to the other and sharing the same schedule, so they open and shut together. Standing in the town-side room (say room 34, whose east side is the gate): {{{ item create town gate item gate desc A great gate of timber bound with black iron, tall enough to admit a laden hay-cart. item gate data fixed true item gate data openable true item gate data exit_to 95 item gate data exit_verbs east, e, gate item gate data open_at 5 item gate data close_at 20 item gate data open_msg With a groan of timber and iron, the town gate swings open to the dawn. item gate data close_msg The town gate swings shut, barring the road for the night. item gate data ground_open The great town gate stands open to the east. item gate data ground_closed The great town gate is shut, barring the road east. }}} Then build the twin in room 95 the same way, but with **exit_to 34** and **exit_verbs west, w, gate** (and its ground lines facing //west//). Finally, **undig east** here to clear the plain cardinal passage between the two rooms, so the gate is the //only// way through -- otherwise a walker (or a fleeing player, or a wandering mob) could slip past a shut gate by the old exit. From dawn to dusk the road runs open; at nightfall it bars, and anyone caught outside waits for morning. == Day/night schedules -- mobs that keep hours Just as an object can follow the [[How to Play|game clock]], so can a mobile. Give it a **day_room** and a **night_room** and it keeps to one by daylight and the other after dark -- the graveyard caretaker who works his office through the day and shuts himself in his house at night. Set it on the mob with **mob //ref// data //field// //value//**: * **data day_room //room#//** -- where it stays through the daylight hours (dawn through dusk, roughly 05:00-19:59). * **data night_room //room#//** -- where it moves for the night (nightfall through pre-dawn, 20:00-04:59). * **data sched_night_leave //line//** -- announced in the //day// room as it heads off for the night (optional). * **data sched_night_arrive //line//** -- announced in the //night// room as it arrives (optional). * **data sched_day_leave //line//** -- announced in the //night// room as it sets off at dawn (optional). * **data sched_day_arrive //line//** -- announced in the //day// room as it returns for the day (optional). Both rooms are required for the schedule to engage. The mob simply //appears// in the right room -- it doesn't walk the halls between, so the two rooms may sit anywhere in the world. The clock's hourly tick relocates it as the day/night line is crossed, and a daemon restart snaps it straight to wherever the current hour says it belongs (so a restart at midnight finds the caretaker already home). Unlike a timed gate, the four messages have no default -- leave one unset and that crossing passes silently. === A worked example: the graveyard caretaker The caretaker works from his office (room 151) by day and retires to his house (room 150) at night: {{{ mob create caretaker mob caretaker data day_room 151 mob caretaker data night_room 150 mob caretaker data sched_night_leave The caretaker locks up the office and shuffles off toward his house. mob caretaker data sched_night_arrive The caretaker lets himself in and bars his door against the night. mob caretaker data sched_day_leave The caretaker steps out into the grey dawn and shuffles off toward the office. mob caretaker data sched_day_arrive The caretaker unlocks the office, hangs up his lamp, and settles in for the day. }}} == Resetting flags on a zone reset Zones reset about once an hour on their own, and a builder can force one with **zone reset** (the whole world, as the hourly timer does) or **zone reset //zone#//** (just that one zone's corpses, spawns, and flags). A reset is deliberately **light-touch**: it **replaces anything missing** from its spawn template, but it does **not** tear down or rebuild things that are still there. So by default a prop or mob keeps whatever drifted about it -- a lever someone uncovered stays uncovered, a shopkeeper keeps (and goes on selling) items players handed it. Often that persistence is exactly what you want; sometimes it isn't. When you want a specific flag to snap back to a base state every reset, declare it with an **onreset_//field//** directive on the item, mob, **or room**: * **data onreset_//field// //value//** -- on each reset, **data //field//** is set back to //value//. //e.g.// **data onreset_invisible true** re-hides a searched-out prop; **data onreset_locked true** re-locks a door. * **data onreset_//field// off** (or **none** / **clear**) -- on each reset, the field is **removed** -- the way to force a flag back //off//. //(A literal// **onreset_//field// false** //won't store: setting any data field to// **false** //clears it, so the directive would vanish. Use// **off** //instead.)// * The **onreset_** directives themselves are never touched -- they're the standing definition of the base state, not a one-shot. Only the named flags are rewritten (and only when they've actually drifted, so it's cheap); everything else the thing has accumulated is left intact. This is the deliberate alternative to deleting and respawning just to fix a flag -- ids stay stable, nothing is yanked from a player mid-use, and a mob's gathered inventory survives. A thing with **no** onreset_ directives simply keeps its flags across resets. {{{ (a wall switch in a room that players flip to open something; reset it each hour) item create switch item switch data fixed true item switch data verb_flip You throw the switch with a heavy clunk. item switch data onreset_flipped off (base state: not flipped) drop switch }}} On a **room**, the natural use is re-sealing a secret exit a lever opened (see **Hidden exits** above): standing in the room, **room data onreset_hidden_west true** makes the west passage close again every reset, so the search-and-pull puzzle is fresh for the next player. == Multi-room puzzles: zone flags and gates Everything above happens in one room. For a puzzle that spans an area -- light three braziers scattered across the sewers and a stone door grinds open somewhere else -- you need a shared scratchpad above the single room. That is the **zone blackboard**: each zone carries its own set of flags, and props raise them while a **gate** elsewhere watches for the right combination. === Raising a zone flag * **data verb_//word//_zoneflag //flag//** -- doing //word// to this prop sets //flag// on the current zone's blackboard (and prints the prop's **verb_//word//** line as usual). Give each source its //own// flag. //e.g.// three braziers with **verb_light_zoneflag brazier_a**, **...brazier_b**, **...brazier_c**. * Raising a flag is **one-way and idempotent** -- lighting an already-lit brazier just says "It is already done." The flags are cleared on a **zone reset**, so the puzzle re-arms. === Requiring a tool in hand Often the action needs an implement -- you can't light a brazier bare-handed: * **data verb_//word//_needs //dataflag//** -- the actor must be **holding** an item whose data has //dataflag// set, or the action is refused and //no flag is raised//. * **data verb_//word//_needs_fail //line//** -- the refusal message (optional; a plain default is used otherwise). //e.g.// a brazier with **data verb_light_needs hasfire** can only be lit while you carry something marked **data hasfire true** (the newbie torch is). "Light" also handles a prop that isn't a carried lamp, so **light brazier** reaches this hook. === The gate A **gate** is a room that opens when the flags line up. It reuses **Hidden exits**: seal the way with **hidden_//dir//**, then -- * **room data gate_needs //flag,flag,...//** -- the flags that must //all// be set. * **room data gate_exit //dir//** -- the hidden exit to un-seal when they are (one-way). * **room data gate_message //line//** -- announced to **everyone in the zone** ("//You hear a stone door grind open, somewhere in the distance.//"). * **room data gate_item //keyword//** -- //optional//: a prop in the gate room to flip to its **open** look at the same moment, so a great stone visibly grinds aside (see below). === A worked example: three braziers and a stone gate {{{ (a brazier in each of three rooms) item create brazier item brazier data fixed true item brazier data verb_light The brazier catches with a roar, flames clawing at the ceiling. item brazier data verb_light_zoneflag brazier_a (b and c in the other two rooms) item brazier data verb_light_needs hasfire (needs a torch in hand) (the gate room, its down stair sealed) room data hidden_down true room data onreset_hidden_down true (re-seals every reset) room data gate_needs brazier_a,brazier_b,brazier_c room data gate_exit down room data gate_message You hear a stone door grind open, somewhere in the distance. room data gate_item gate (the stone prop to slide aside) (the stone itself: a prop that shows its state, flipped by the gate -- not player-openable) item create stone gate item gate data fixed true item gate data ground_closed A colossal stone slab is sunk into the floor here, sealing a stairwell beneath it. item gate data ground_open The colossal stone has ground aside, baring a stair down into the dark. item gate data open false item gate data onreset_open off (re-seals with the exit on reset) drop gate }}} Now a player with a torch **light**s all three braziers (in any order); on the third, the down stair un-seals, the stone grinds aside, and the whole zone hears it. An hour later the reset clears the flags, re-seals the exit, and re-closes the stone -- fresh for the next party. The open/closed //ground// text (above) works for any prop, not just gates: give an item both lines and its listing follows its **open** flag. ---- See also: **[[How to Build]]**, **[[All about Items]]**, **[[All about Mobiles]]**, **[[How to Play]]**.