-
Notifications
You must be signed in to change notification settings - Fork 18
Scope
Determining what item should be listed when is very complicated once you have a sophisticated world-model. Some issues are:
- A room within a room (for example, the player might be stood on a chair that is inside a cage, which in turn is in a hall)
- An item that is in more than one room (for example, a door is likely to be in two rooms)
- Items in containers that could be open or closed, transparent or opaque, or inside another container
- Items held or worn by NPCs
- Items that can or cannot be found when it is dark
- Items considered scenery
- Some instances of a countable could be in a container, whilst others are in another room and still more are held.
My first attempt at this involved iterating through every object, and for each object is turn, iterating through everything to see if it was accessible. For 100 objects, that would be 10,000 tests, which might be done four or five times a command. I have now abandoned that for a system that involves storing a snapshot of the scope at a moment in time. This has a very real risk that it could expire if not updated when the world changes. However, tests are now running at about 2.8 ms each, rather than about 4.2 ms.
You can call game.update() to ensure scope is up-to-date after moving the player or an item, changing lighting, opening/closing, etc. if this is going to be an issue. This is called at the end of each turn anyway to ensure the side pane is right; you would only need to call it yourself if you are modifying the world and then have some further processing to do.
Items that are in scope will be in the list world.scope which is re-built when a snapshot is taken. This will include the room itself, as of version 1.0.1.
By default, commands are restricted to items in world.scope, but you can change that for a specific command (see here).
getContents(situation) will return the child objects of a room, container, surface or NPC, i.e., all items that return true for isAtLoc with the given situation.
isAtloc(loc, situation) will return true if the object is at the named location. This can be modified for items in odd situations. The background object returns true because it is everywhere, a component returns true if its parent is here.
canReachThrough() will return true if you can access the contents (the contain is open, or whatever)
canSeeThrough() will return true if you can access the contents (the contain is open, or whatever)
scopeSnapshot(visible) sets the scope snapshot for this and its contents
The primary scope function is scopeBy. It takes a function parameter that determines if an item is to be included. Here is an example that will get all items with an "activeEffects" attribute.
const objs = scopeBy(function(el) { return el.activeEffects !== undefined })JavaScript has a shortcut that is less typing, but less clear what is going on. This example is the same as the one above:
const objs = scopeBy(el => el.activeEffects !== undefined )There are some built-in scope functions too.
// Returns an array of objects the player can currently reach and see.
function scopeReachable()
// Returns an array of objects held by the given character.
function scopeHeldBy(chr, situation = world.PARSER)
// Returns an array of objects at the player's location that can be seen.
function scopeHereListed()
// Returns an array of objects at the player's location that can be seen.
function scopeHereParser()
// Returns an array of NPCs at the player's location (excludes those flagged as scenery).
function scopeNpcHere(ignoreDark)
// Returns an array of NPCs at the player's location (includes those flagged as scenery).
function scopeAllNpcHere(ignoreDark)The parser also has its own set of scope functions.
The scope revolves around two attributes, scopeStatus and scopeStatusForRoom, so the first thing scopeSnapshot does is delete these for all objects.
Next we find the highest level room the player is in and is reachable (so if the player is in a barred cage, in a lab, the lab is reachable too). Each room has scopeStatusForRoom flagged as REACHABLE. We then call scopeSnapshot on the room object, with false to set the reachable objects.
Then we do the same thing again for visible, rather than reachable, and call scopeSnapshot on the highest room object, with true.
The scopeSnapshot function takes a boolean, true if we are checking visible, false for reachable. It firstly checks to see if scopeStatus is already set - if it is, this object has already been done, so nothing more happens. If not, this object is set to be visible or reachable.
If this is a container or has components, then we need to check though them, and the rest of the function does that, calling scopeSnapshot for any contained objects as appropriate.
Tutorial
- First steps
- Rooms and Exits
- Items
- Templates
- Items and rooms again
- More items
- Locks
- Commands
- Complex mechanisms
- Uploading
QuestJS Basics
- General
- Settings
- Attributes for items
- Attributes for rooms
- Attributes for exits
- Naming Items and Rooms
- Restrictions, Messages and Reactions
- Creating objects on the fly
- String Functions
- Random Functions
- Array/List Functions
- The
respondfunction - Other Functions
The Text Processor
Commands
- Introduction
- Basic commands (from the tutorial)
- Complex commands
- Example of creating a command (implementing SHOOT GUN AT HENRY)
- More on commands
- Shortcut for commands
- Modifying existing commands
- Custom parser types
- Note on command results
- Meta-Commands
- Neutral language (including alternatives to "you")
- The parser
- Command matching
- Vari-verbs (for verbs that are almost synonyms)
Templates for Items
- Introduction
- Takeable
- Openable
- Container and surface
- Locks and keys
- Wearable
- Furniture
- Button and Switch
- Readable
- Edible
- Vessel (handling liquids)
- Components
- Countable
- Consultable
- Rope
- Construction
- Backscene (walls, etc.)
- Merchandise (including how to create a shop)
- Shiftable (can be pushed from one room to another)
See also:
- Custom templates (and alternatives)
Handing NPCs
- Introduction
- Attributes
- Allowing the player to give commands
- Conversations
- Simple TALK TO
- SAY
- ASK and TELL
- Dynamic conversations with TALK TO
- TALK and DISCUSS
- Following an agenda
- Reactions
- Giving
- Followers
- Visibility
- Changing the player point-of-view
The User Experience (UI)
The main screen
- Basics
- Printing Text Functions
- Special Text Effects
- Output effects (including pausing)
- Hyperlinks
- User Input
The Side Panes
Multi-media (sounds, images, maps, etc.)
- Images
- Sounds
- Youtube Video (Contribution by KV)
- Adding a map
- Node-based maps
- Image-based maps
- Hex maps
- Adding a playing board
- Roulette!... in a grid
Dialogue boxes
- Character Creation
- Other example dialogs [See also "User Input"]
Other Elements
- Toolbar (status bar across the top)
- Custom UI Elements
Role-playing Games
- Introduction
- Getting started
- Items
- Characters (and Monsters!)
- Spawning Monsters and Items)
- Systema Naturae
- Who, When and How NPCs Attack
- Attributes for characters
- Attacking and guarding
- Communicating monsters
- Skills and Spells
- Limiting Magic
- Effects
- The Attack Object
- [Extra utility functions](https://github.com/ThePix/QuestJS/wiki/RPG-Library-%E2%80%90-Extra Functions)
- Randomly Generated Dungeon
- Quests for Quest
- User Interface
Web Basics
- HTML (the basic elements of a web page)
- CSS (how to style web pages)
- SVG (scalable vector graphics)
- Colours
- JavaScript
- Regular Expressions
How-to
Time
- Events (and Turnscripts)
- Date and Time (including custom calendars)
- Timed Events (i.e., real time, not game time)
Items
- Phone a Friend
- Using the USE verb
- Display Verbs
- Change Listeners
- Ensembles (grouping items)
- How to spit
Locations
- Large, open areas
- Region,s with sky, walls, etc.
- Dynamic Room Descriptions
- Transit system (lifts/elevators, buses, trains, simple vehicles)
- Rooms split into multiple locations
- Create rooms on the fly
- Handling weather
Exits
- Alternative Directions (eg, port and starboard)
- Destinations, Not Directions
Meta
- Customise Help
- Provide hints
- Include Achievements
- Add comments to your code
-
End The Game (
io.finish)
Meta: About The Whole Game
- Translate from Quest 5
- Authoring Several Games at Once
- Chaining Several Games Together
- Competition Entry
- Walk-throughs
- Unit testing
- Debugging (trouble-shooting)
Releasing Your Game
Reference
- The Language File
- List of settings
- Scope
- The Output Queue
- Security
- Implementation notes (initialisation order, data structures)
- Files
- Code guidelines
- Save/load
- UNDO
- The editor
- The Cloak of Darkness
- Versions
- Quest 6 or QuestJS
- The other Folders
- Choose your own adventure