From 70da504f9fc217d4ef5672638765aa3a548e7f8a Mon Sep 17 00:00:00 2001 From: Alexander Yakovlev Date: Thu, 24 Jul 2014 16:56:29 +0700 Subject: [PATCH] Initial commit --- LANGS.md | 2 + README.md | 2 + book.json | 3 + en/API.md | 690 +++++++++++++++++++++++++++++++++++++++++++++ en/HTML.md | 302 ++++++++++++++++++++ en/README.md | 1 + en/SUMMARY.md | 4 + en/api.md | 1 + en/base.html | 149 ++++++++++ en/creating.md | 263 +++++++++++++++++ en/files.md | 80 ++++++ en/i18n.md | 98 +++++++ en/implicit.md | 204 ++++++++++++++ en/index.md | 71 +++++ en/introduction.md | 54 ++++ ru/README.md | 1 + ru/SUMMARY.md | 4 + ru/api.md | 1 + 18 files changed, 1930 insertions(+) create mode 100644 LANGS.md create mode 100644 README.md create mode 100644 book.json create mode 100644 en/API.md create mode 100644 en/HTML.md create mode 100644 en/README.md create mode 100644 en/SUMMARY.md create mode 100644 en/api.md create mode 100644 en/base.html create mode 100644 en/creating.md create mode 100644 en/files.md create mode 100644 en/i18n.md create mode 100644 en/implicit.md create mode 100644 en/index.md create mode 100644 en/introduction.md create mode 100644 ru/README.md create mode 100644 ru/SUMMARY.md create mode 100644 ru/api.md diff --git a/LANGS.md b/LANGS.md new file mode 100644 index 0000000..7b46017 --- /dev/null +++ b/LANGS.md @@ -0,0 +1,2 @@ +* [English](en/) +* [Russian](ru/) diff --git a/README.md b/README.md new file mode 100644 index 0000000..bdb3dba --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# Undum 2 documentation +Gitbook format diff --git a/book.json b/book.json new file mode 100644 index 0000000..3936e96 --- /dev/null +++ b/book.json @@ -0,0 +1,3 @@ +{ + "output": null, +} diff --git a/en/API.md b/en/API.md new file mode 100644 index 0000000..34b1b60 --- /dev/null +++ b/en/API.md @@ -0,0 +1,690 @@ +# Javascript API + +# `Character` + +The character is created for you, but is passed into most of the +functions that you define. It consists of an object with no methods +and two properties: + +#### `qualities` + +The qualities object maps quality identifiers to their current +value. Your code finds the current value associated with a quality by +reading from this object, for example: + + var gold = character.qualities.gold; + +To set a quality, you have two choices. If you know the quality you +want to set will not appear in the user interface, then you can set it +directly: + + character.qualities.gold += 1; + +If it does appear on-screen, then this approach will mean that the +character panel doesn't update, and the screen will be out of sync +with the actual value. Instead it is better to use the `System` method +`setQuality`, which also updates the UI: + + system.setQuality('gold', character.qualities.gold+1); + +It is fine to use `setQuality` if the quality isn't visible, making +this the preferred option for all quality modifications. + +#### `sandbox` + +Not every bit of data you want to associate with a character fits +nicely into a quality. The sandbox is a general storage space for any +further data you want to store in the course of your game, for +example: + + character.sandbox.roomsSearched.push('bathroom'); + +Sandbox data is never visible to the user, so you can use any data +structures you like here, to any depth. + +# `System` + +The system represents the interface between your code and the +user-interface. You don't create your own `System` object, it is +passed into your code. + +#### `clearContent(elementSelector)` + +*Since version 2* + +Removes all content from the page, clearing the main content area. + +Although Undum is designed to keep the flow of the narrative on one +page, sometimes you do need to start a new page, and this allows you +to do so. + +The `elementSelector` is options. If you give it, then the DOM element +matching the selector is cleared, rather than the whole document. + +#### `write(content, elementSelector)` + +Writes new content to the main flow of the story. The content you pass +in must be either valid DOM elements already, or else be a string +containing text in Display Content format. + +The `elementSelector` is optional. If you provide it, then the new +content will be added after the DOM element in the document that +matches the selector. This allows you to do out-of-order addition of +content. Simply add a paragraph with an id in your game, then later +you can give this id as a selector to write, and the new content will +be inserted immediately following that paragraph, regardless of how +much extra content has been added since that point. If no selector is +given then `#content` is used, i.e. the content is added at the end of +the document. The `writeBefore` method inserts content at the start of +the document, or before a selector. + +The story will scroll to the start of the insertion point. If you do +not wish to animate this scrolling, but just jump right there, you can +switch off jQuery's animation system by adding `jQuery.fx.off=true` to +your initialization code. This is particularly useful when debugging. + +#### `writeHeading(content, elementSelector)` + +Writes new content into the story and formats it as a heading. This +method work exactly as `write`, but wraps the content you provide into +a `h1` html tag. + +#### `writeBefore(content, elementSelector)` + +Writes content into the story. This method is identical to `write`, +above, except that the content is written at the start of the story, +or if a selector is given, inserted before the matching element. On +browsers that support it, the story will be scrolled to the insertion +point. + +#### `writeChoices(listOfSituationIds)` + +*Since version 2* + +Creates a standard block of choices, one for each of the given +situation ids. The text used in the links will be whatever is returned +by the situation's `optionText` method. In addition, if the +situation's `canChoose` method returns `false`, then the option will +be displayed, but will not be clickable. + +#### `getSituationIdChoices(listOfIdsOrTags, minChoices, maxChoices)` + +*Since version 2* + +This function is a complex and powerful way of compiling implicit +situation choices. You give it a list of situation ids and situation +tags. Tags should be prefixed with a hash # to differentiate them from +situation ids. The function then considers all matching situations in +descending priority order, calling their canView functions and +filtering out any that should not be shown, given the current +state. Without additional parameters the function returns a list of +the situation ids at the highest level of priority that has any valid +results. So, for example, if a tag #places matches three situations, +one with priority 2, and two with priority 3, and all of them can be +viewed in the current context, then only the two with priority 3 will +be returned. This allows you to have high-priority situations that +trump any lower situations when they are valid, such as situations +that force the player to go to one destination if the player is out of +money, for example. + +If a `minChoices` value is given, then the function will attempt to +return at least that many results. If not enough results are available +at the highest priority, then lower priorities will be considered in +turn, until enough situations are found. In the example above, if we +had a minChoices of three, then all three situations would be +returned, even though they have different priorities. If you need to +return all valid situations, regardless of their priorities, set +minChoices to a large number, such as `Number.MAX_VALUE`, and leave +maxChoices undefined. + +If a `maxChoices` value is given, then the function will not return any +more than the given number of results. If there are more than this +number of results possible, then the highest priority resuls will be +guaranteed to be returned, but the lowest priority group will have to +fight it out for the remaining places. In this case, a random sample +is chosen, taking into account the frequency of each situation. So a +situation with a frequency of 100 will be chosen 100 times more often +than a situation with a frequency of 1, if there is one space +available. Often these frequencies have to be taken as a guideline, +and the actual probabilities will only be approximate. Consider three +situations with frequencies of 1, 1, 100, competing for two +spaces. The 100-frequency situation will be chosen almost every time, +but for the other space, one of the 1-frequency situations must be +chosen. So the actual probabilities will be roughly 50%, 50%, +100%. When selecting more than one result, frequencies can only be a +guide. + +Before this function returns its result, it sorts the situations in +increasing order of their `displayOrder` properties. + + +#### `doLink(URL)` + +Carries out the action associated with the given URL, as if it had +been the `href` of a HTML link that the user clicked. This allows you +to procedurally change situation and carry out actions from your code. + +#### `rnd` + +This holds a general purpose random number generator. It is an object +derived from the `Random` prototype, so see `Random` below for details +on its API. + +#### `time` + +This is a numeric value holding the current time, in seconds, since +the player began playing the game. This value is correctly propagated +across saves, so it is the only way you should track timing. In +particular you should never call `new Date()` and use that value to +determine the outcome of any event. You can use the current date to +display the current date, for example, but not to control what actions +or situations are available. See the section on Loading and Saving for +more details of why this is important. + +#### `setQuality(qualityId, newValue)` + +Sets the character's given quality to the given value. This function +also updates the character panel, animating the change in value if +that is necessary. Do not directly set quality values in the +character, because the user-interface will not detect and reflect +those changes. + +#### `animateQuality(qualityId, newValue, options)` + +Like `setQuality`, this function changes the current value of the +given quality. In addition, however, it displays a progress bar that +shows to the user how the value has changed. The `options` parameter +should be an object containing options for how the bar should +display. The available options are: + +- `from`: The proportion along the progress bar where the animation + starts. Defaults to 0, valid range is 0-1. + +- `to`: The proportion along the progress bar where the animation + ends. Defaults to 1, valid range is 0-1. + +- `showValue`: If `true` (the default) then the new value of the + quality is displayed above the progress bar. + +- `displayValue`: If this is given, and `showValue` is `true`, then + the given value is used above the progress bar. If this isn't + given, and `showValue` is `true`, then the display value will be + calculated from the `QualityDefinition`, as normal. This option is + useful for qualities that don't have a definition, because they + don't normally appear in the UI. + +- `title`: The title of the progress bar. If this is not given, then + the title of the quality is used. As for `displayValue` this is + primarily used when the progress bar doesn't have a + `QualityDefinition`, and therefore doesn't have a title. + +- `leftLabel`, `rightLabel`: Underneath the progress bar you can place + two labels at the left and right extent of the track. These can + help to give scale to the bar. So if the bar signifies going from + 10.2 to 10.5, you might label the left and right extents with "10" + and "11" respectively and have the `from` and `to` value be 0.2 and + 0.5 respectively. If these are not given, then the labels will be + omitted. + +#### `setCharacterText(content)` + +Sets the block of character text that appears in the character +panel. As for the `write` method, this text should be either valid DOM +elements, or a string meeting the Display Content requirements. + +#### `clearLinks(URL)` + +Call this function with an Undum link URL (e.g. `ballroom`, or +`ballroom/open-cabinet`). It will remove all occurrences of that link +from the page. This is equivalent to what happens when you change +situation, or when you click a link marked with the `once` CSS +class. It allows you to control what options are available +dynamically, from your code. + +## `Random` + +The `Random` object provides a set of tools for simple random number +generation, in a way that is guaranteed to work with the Loading and +Saving functionality in Undum. An instance of `Random` is provided in +the `rnd` property of the `System` object, so you will never need to +create your own. It has the following methods: + +#### `random()` + +Generates a random number between 0 and 1, where 0 is inclusive, and 1 +is exclusive. You can use this to check against known probabilities, +such as: + + if (system.rnd.random() > 0.5) { + ... + } + +To check for a 50/50 chance. + +#### `randomInt(min, max)` + +Return a random number between the given two values, where both values +are inclusive. So `randomInt(2,3)` generates either 2 or 3. + +#### `dice(n, dx, plus)` + +Rolls _n_ dice with _dx_ sides and adds _plus_ to the result. This +allows you to easily get results for rolls from regular RPG-style +games, such as 3d6+2. The `plus` parameter may be negative or +positive. + +#### `aveDice(n, plus)` + +Rolls _n_ averaging dice, and adds _plus_ to the result. Averaging dice +are a special type of d6 with sides marked [2,3,3,4,4,5]. They represent +the fact that most people are fairly average, and results should not lie +at the extremes. + +#### `diceString(definition)` + +Rolls dice according to the given definition string. The string should +be of the form xdy+z, where the x component and z component are +optional. This rolls x dice of with y sides, and adds z to the result, +the z component can also be negative: xdy-z. The y component can be +either a number of sides, or can be the special values 'F', for a +fudge die (with 3 sides, +,0,-), '%' for a 100 sided die, or 'A' for +an averaging die (with sides 2,3,3,4,4,5). + +# `Situation` + +The `Situation` object is the prototype of all the situations in your +game. It can be used directly, or through its more common derived +type, `SimpleSituation`. The base `Situation` gives you maximum +flexibility, but `SimpleSituation` provides more functionality and can +produce terser code. + +#### `new Situation(options)` + +Creates a new situation. The options array can specify your +implementation for any or all of the following methods of this class: + +- `enter` +- `exit` +- `act` +- `optionText` +- `canView` +- `canChoose` + +(see below for explanations of those methods). This allows +you to easily create situations that override certain behaviors with +code such as: + + Situation({ + enter: function(character, system, from) { + ... your implementation ... + } + }); + +without having to subclass `Situation` to provide your own +implementations. + +In addition the following options can be passed in. + +- `tags`: A list of tags with which to label this situation. These are +primarily used to generate implicit lists of choices with +`System.getSituationIdChoices`. Tags are arbitrary strings. You can +pass a list of strings, or a single string. If you pass a single +string, it will be split at spaces, commas and tabs to form a list of +tags. For this reason, tags normally do not contain spaces, commas or +tabs (though if you pass in a list, and don't expect Undum to do the +splitting for you, you can include any characters you like in a tag). + +- `optionText` (as a string): If given as a string, rather than a +function, this text will be returned whenever `optionText(...)` is +called. + +- `displayOrder`: A numeric value, defaults to 1. When displaying +lists of implicitly generated choices, the options be displayed in +increasing value of this parameter. + +- `priority`: Can be any number, defaults to 1. When generating lists +of choices implicitly, situations are considered in descending +priority order. If higher priority situations can be displayed, lower +priority situations will be hidden. See `System.getSituationIdChoices` +for details of the algorithm. + +- `frequency`: Any number, defaults to 1. When generating lists of +implicit choices, where there are more choices available that slots to +display them, situations will be chosen randomly, with a probability +based on this value. See `System.getSituationIdChoices` for details of +the algorithm. + +#### `enter(character, system, from)` + +This is called when Undum enters a situation. The `character` and +`system` are instances of `Character` and `System` as described +above. The `from` parameter is a string containing the situation +identifier for the situation that we're arriving from. + +This method is the most commonly overridden. It is commonly used to +describe the current situation (by sending content to +`system.write()`) and to update the character (by calling +`system.setQuality()` or by changing data in the character's `sandbox` +object).. + +#### `exit(character, system, to)` + +This method takes the same `character` and `system` parameters as +`enter`. Its third parameter, `to`, is a string containing the +identifier of the situation we're exiting to. + +#### `act(character, system, action)` + +This method again takes the same `character` and `system` parameters +as before. Its third parameter is a string containing the action +identifier corresponding to the link the player clicked. It is common +to use an `if` statement or a `switch` to query this action identifier +and decide what to do accordingly. For situations in which many +different actions are possible, consider using the `SimpleSituation` +prototype, which provides this switching behavior for you. + +#### `optionText(character, system, hostSituation)` + +This method is called by `System.writeChoices` to generate a label for +links to this situation. The `hostSituation` is the situation that has +asked for the choices to be displayed. + +#### `canView(character, system, hostSituation)` + +This method is called by `System.getSituationIdChoices` to determine +whether this situation can be part of a list of choices in the current +game state. It should return true or false. + +#### `canChoose(character, system, hostSituation)` + +This method is called by `System.writeChoices` to determine whether a +link should be added to allow the user to enter this situation. If +not, the choice will still appear, but will not be clickable. + + + +## SimpleSituation + +This prototype builds on the basic `Situation`, providing tools to +make it easy to output content in the `enter` method, and to switch +between different functions depending on the action identifier passed +into the `act` method. The `exit` method of `SimpleSituation` is +exactly as for the base type `Situation`. + +#### `new SimpleSituation(content, options)` + +Creates a new simple situation that will display the given content +when its `enter` method is called. The given options dictionary +provides further control of the behavior of this type. Valid options +are: + +- `enter`: Providing an enter function in the `options` parameter + allows you to add additional behavior to the enter method. Your + custom function will be called *in addition to* and *after* the + default content is written to the screen. You cannot override + `SimpleSituation`'s `enter` method by providing this function. To + override the method, you would have to create a derived type. If + you provide an `enter` function, it should have the same form as + `Situation.enter`. + +- `act`: Pass in a function to add additional behavior to the act + method. As for `enter`, your method is called *in addition to* and + *after* the built-in functionality. + +- `exit`: Because `SimpleSituation` has no default behavior for + `exit`, any function you pass in here will be the only exit + behavior for the object you are creating. + +- `heading`: The `content` that you specify will be written out + verbatim. You can include headings in this content. Often it is + more convenient to pass in just the text in the `content` + parameter. In that case you may define this `heading` parameter to + display a heading before the text. Unlike `content`, this doesn't + need to conform to the Display Content requirements. + +- `actions`: This should be an object that maps action identifiers to + responses. A response should be either some Display Content to + write to the screen, or a function that will process that + request. These functions should have the same signature as the + `Situation.act` method. Each function will only be called if the + situation receives a call to `act` with its corresponding + identifier. This allows you to simply define functions that only + get called when particular actions happen. + +- `choices`: An optional list of tags and situation-ids, with tags + prefixed by a has symbol to distinguish them from situation ids. If + given, this will cause the SimpleSituation to output an implicit block + of choices after the content. + +- `minChoices`: If you have given a `choices` definition, you can set + this to an integer value to change the number of choices that will + appear. See `System.getSituationIdChoices` for more information on + how this affects the output. + +- `maxChoices`: If you have given a `choices` definition, you can set + this to an integer value to change the number of choices that will + appear. See `System.getSituationIdChoices` for more information on + how this affects the output. + +An example `SimpleSituation` definition might be: + + new SimpleSituation( + "

...content...

", + { + heading: "Title", + actions: { + listen: function(character, system, action) { + if (character.qualities.hearing > 5) { + system.write("

You hear a tinkling inside.

"); + } else { + system.write("

You hear nothing.

"); + } + }, + search: "

You find nothing.

" + } + } + ); + +notice how the `listen` function is responsible for its own output, +where the `search` property is a string in Display Content format, +ready for output. + +#### Functions in `SimpleSituation` + +Both the `content` and the `heading` of a simple situation can be +provided either as plain text, or as a function. If you provide a +function, then it will be called with no arguments, and it should +return a string to use for the output. This enables `SimpleSituation` +to be used with other formatting and templating systems. + +# QualityDefinition + +Quality definitions tell Undum how and where to display a quality in +the character panel. Each quality definition has one method, `format`, +which is responsible for converting a numeric quality value into a +displayable quantity. + +You define your qualities in your `undum.game.qualities` property. + + +#### `new QualityDefinition(title, options)` + +Creates a new `QualityDefinition`. It is rare to call this constructor +yourself, most often one of the derived types of `QualityDefinition` +are used. They are defined below. + +The `title` should be a string, and can contain HTML. It is used to +label the quality in the character panel. It can be any string, it +doesn't have to be in Display Content format. + +Options are passed in in the `options` parameter. The following +options are available. + +- `priority`: A string used to sort qualities within their + groups. When the system displays a list of qualities they will be + sorted by this string. If you don't give a priority, then the title + will be used, so you'll get alphabetic order. Normally you either + don't give a priority, or else use a priority string containing + 0-padded numbers (e.g. "00001"). + +- `group`: The identifier of a group in which to display this + parameter. If a group is given, then it must be defined in your + `undum.game.qualityGroups` property. + +- `extraClasses`: These classes will be attached to the `
` tag + that surrounds the quality when it is displayed. A common use for + this is to add icons representing the quality. In your CSS define a + class for each icon, then pass those classes into the appropriate + quality definitions. + +#### `format(character, value)` + +This is called by Undum to get a human readable string representing +the given quality value for the given character. The method may return +an empty string if the value has no need to be displayed, or it may +return `null` if the quantity itself shouldn't be displayed. The +difference here is significant. If your `QualityDefinition` returns +the empty string, then the quality will appear in the character panel, +but it will have no value marked. If it returns `null`, then it will +be removed from the character panel entirely. + +Most commonly the `character` parameter is ignored, but in your own +derived types you can take advantage of being able to access other +information about the character. + +You may call this function yourself, but there is commonly no need. It +will be called by Undum any time the corresponding quality needs to be +displayed. + +## `IntegerQuality` + +This is a derived type of `QualityDefinition` that displays the +quality value by rounding it down to the nearest integer. This is +ideal for most numeric statistics. + +## `NonZeroIntegerQuality` + +This is a derived type of `IntegerQuality` that only displays its +value when it is non-zero. If it is non-zero then it formats in the +same way as `IntegerQuality`. Whereas `IntegerQuality` whould show +zero values as '0', this type of quality displays nothing. + +## `NumericQuality` + +This is a derived type of `QualityDefinition` that displays the +quality value directly, as a full floating point value. + +## `WordScaleQuality` + +Sometimes you want qualities displayed in words rather than +numbers. This is a derived type of `QualityDefinition` that allows you +to define words corresponding to possible quality values. + +#### `new WordScaleQuality(title, words, options)` + +The `title` parameter is exactly as for `QualityDefinition`. + +The `words` parameter determines what words will be used. It should be +an array of strings. By default the first string will be used to +represent a value of zero (after rounding down), and the second string +a value of 1, and so on to the end of the array. Values outside the +array are treated differently depending on the value of `useBonuses` +in the `options` parameter. + +The `options` parameter supports the same three options as +`QualityDefinition`. It also takes the following additional +parameters: + +- `offset`: With offset=0 (the default), a quantity value of 0 will + map to the first word, and so on. If offset is non-zero then the + value given will correspond to the first word in the list. So if + offset=4, then the first word in the list will be used for value=4, + the second for value=5. You can specify a non-integer offset value, + in this case the offset is applied *before* the value is rounded + down. + +- `useBonuses`: If this is true (the default), then values outside the + range of words will be constructed from the word and a numeric + bonus. So with offset=0 and five words, the last of which is + 'amazing', a score of six would give 'amazing+1'. if this is + false, then the bonus would be omitted, so anything beyond + 'amazing' is still 'amazing'. + +## `FudgeAdjectivesQuality` + +This is a derived type of `WordScaleQuality` that doesn't require you +to specify the words you wish to use. It uses the word scale from the +Fudge RPG: "terrible", "poor", "mediocre", "fair", "good", "great" and +"superb". + +#### `new FudgeAdjectivesQuality(title, options)` + +The parameters `title` and `options` are as for the `WordScaleQuality` +constructor. The `offset` option defaults to -3, however (in +`WordScaleQuality` it defaults to 0), making "fair" the display value +for 0. + +## `OnOffQuality` + +An `OnOffQuality` returns `null` from its `format` method +(i.e. removes itself from the character panel) when the corresponding +quality value is zero. Otherwise it returns the empty string (i.e. it +is shown in the panel, but doesn't have a value label). See +`QualityDisplay.format` above for more details on this distinction. + +#### `new OnOffQuality(title, options)` + +The constructor for this type is the same as for `QualityDefinition` +from which it is derived. It accepts one extra option: + +- `onDisplay`: If given, then rather than displaying the empty string, + it displays the given string when its corresponding value is + non-zero. This can be used to display a check-mark, for example + (`{onDisplay:"✓"}`), or even a HTML `img` tag. + +## YesNoQuality + +A `YesNoQuality` displays one of two strings depending whether its +value is zero or not. + +#### `new YesNoQuality(title, options)` + +The constructor for this type is the same as for `QualityDefinition` +from which it is derived. It accepts two extra options: + +- `yesDisplay`, `noDisplay`: Either or both of these may be given. If + they are given, then they should be set to a string, which will be + used to indicate non-zero or zero values, respectively. By default + "yes" and "no" are used. + +# `QualityGroup` + +A quality group defines a set of qualities that should be displayed +together in the character panel, under an optional subheading. You +could use quality groups to distinguish between qualities representing +a character's innate abilities and their equipment, for example. + +You define your quality groups in your `undum.game.qualityGroups` +property. + + +#### `new QualityGroup(title, options)` + +Constructs a new quality group that will have the given `title` for a +subheading. The title may be `null`, indicating that this group does +not need a heading. + +The `options` parameter should be an object with the given optional +parameters: + +- `priority`: A string used to sort quality groups. When the system + displays more than one quality group, they will be sorted by this + string. If you don't give a priority, then the title will be used, + so you'll get alphabetic order. Normally you either don't give a + priority, or else use a priority string containing 0-padded numbers + (e.g. "00001"). + +- `extraClasses`: These classes will be attached to the `
` tag + that surrounds the entire quality group when it is displayed. You + can use this in addition to your CSS to radically change the way + certain qualities are displayed. diff --git a/en/HTML.md b/en/HTML.md new file mode 100644 index 0000000..6c2d412 --- /dev/null +++ b/en/HTML.md @@ -0,0 +1,302 @@ +# HTML API + +# HTML + +All of Undum's output is HTML. This allows you to style your content +in any way you choose. It also allows you to include rich media into +your output, such as images, video or audio. + +## Display Content + +All HTML output should be in a format we call "Display Content" - this +has particular rules: + +* Display Content must always start and end with a HTML tag. It may + consist of more than one tag internally, however. So we can have the + structure: `

...

`, for example, but not `some + text...`. + +* It must be a complete snippet of HTML in its own right. So any tags + that represent a range of content must have their closing tags + present. So we can do `

...

`, but not + `

...

`. + +## CSS Styles + +Undum also uses some of HTML's capabilities to control its own +behavior. In particular, it uses a series of CSS classes to control +how content behaves. + +#### `class="transient"` + +The CSS class `transient` can be used to mark HTML content that should +be removed when the user changes their situation. When a situation +changes, Undum will go back and remove any links from the text +(leaving the text that was in the link). Any HTML content that has the +CSS class `transient` will be completely removed at this time. Undum +uses a fading animation to show the user this is happening, to avoid +the user seeing an abrupt disappearance but being unable to work out +what was removed. + +Any HTML tag can be marked as `transient`. It is most commonly used on +a paragraph of text that gives the user a set of options. Undum is +designed to allow game developers to produce beautiful narratives - +you don't want that narrative littered by "You could do X, or you +could do Y." statements. Mark this content as transient, and it will +not form part of the permanent record. + +#### `class="sticky"` + +When you change situations, links in previous situations will be +removed. This prevents the user backtracking and picking options that +no longer apply. Sometimes you want links to be available for a longer +time, however. In this case mark them with the CSS class +`sticky`. Sticky only applies to links, so should only be added to +`` tags. + +#### `class="raw"` + +Links can also have the `raw` CSS class. This class prevents Undum +from interpreting the link as an instruction to the game. If you want +to add a link to an external resource, you can add this class to +it. Note that raw links are still removed when you change situations, +so if you want a raw link permanently available, you should also make +it sticky. + +For some URLs, Undum can guess that the link is supposed to be an +external link, and will automatically add the `raw` class for +you. This isn't perfect, however, and you are better off not relying +on it. If you have a link that you don't want Undum to capture, always +use the `raw` class. + +#### `class="once"` + +Although links will be removed when the situation changes, often you +want to remove them before that, as a result of an action within the +current situation. There is an API tool available to do that in your +code. + +For convenience, there is also the `once` CSS class. Adding this to a +link means that the link will be removed as soon as it is +clicked. This is mostly useful for action links, because a link that +changes the situation will automatically cause previous links to +disappear. + +Note that once is smart about this removal. It removes all links to +the same action, not just the link that was clicked. So if you have +the same action available in two links in your content, both will be +removed. + +#### `class="options"` + +The options class only works on an unordered list. The default CSS +also styles this differently. The list items will be presented as +options within a table of choices. On devices with a mouse or pointer, +the rows will change color when they are hovered over. The player can +click anywhere on the row and the first link that it contains will be +executed. + +This class is intended for smarter presentation of standard option +blocks, if you don't want your choices to be embedded into the +hypertext. + +Note that if you use this style, the unordered list will automatically +disappear after being clicked, regardless of whether it is marked as +"`transient`". + +### Headings + +In the default CSS for Undum, the only heading level expected in the +text is `

`. You can use other headings, but you'll have to create +your own CSS styles. One level of heading is almost always enough (if +not too much) for narrative works. + + +## Types of Link + +Undum captures the links you put into your display content, and uses +them to control the flow of the game. There are three formats of link +that Undum understands, plus raw links, which it ignores. + +### Situation Links + +Situation links are of the form `situation-id`. They must have no +additional punctuation. As we'll see below, situation identifiers +consist of lower case Latin letters, hyphens and the digits 0-9 only. + +Clicking a situation link changes the current situation. + +### Action Links + +Action links are of the form `./action-id`. As for situations, action +identifiers consist of lower case Latin letters, the digits 0-9 and +hyphens only. + +Clicking an action link carries out the specified action in the +current situation. + +### Combined Links + +Combined links are of the form `situation-id/action-id`. They combine +both the previous steps: they change to the given situation, and then +they carry out the given action once there. They are rarely used. + +It is possible to use the combined form to refer to an action in the +current situation. Undum is smart enough to understand that it doesn't +need to change situation in that case, so it is entirely equivalent to +the action link. It is rarely used (because it is so much more +verbose), but can be useful. For example, we might want a sticky link +to always take the character into their study and drink a potion, +having this sticky link point to `bedroom/drink-potion`, achieves +this. If they are already in the bedroom, then Undum notices this and +doesn't try to make them enter it again. + +### External Links + +As described above, you can add any other links to external content in +your display content, as long as you mark it with the `raw` CSS +class. It is also *highly* recommended that you mark all such links as +opening in a new window or tab (add the `target="_blank"` attribute to +the `` tag). If you link the player to another page, and it +replaces the Undum page, then for most browsers, all progress will be +lost. Chrome appears to keep the progress, so that if you hit the back +button you will be where you left off. Other browsers reset the game +to the last saved location, or back to the beginning if the game +hasn't been saved. + +### Link Data + +*This section describes a feature that is planned, or in development. +It may not be functional in the current version of the code.* + +Undum links are allowed to add query data, +e.g. `./action-id?foo=1&bar=2`. This extra data is URL-encoded content +which will be parsed and passed back to your code. For situation links +the data will be passed into the old situation's `exit` handler, and +the new situation's `enter` handler. For action links, the data will +be passed into the situation's `act` handler. For combined links the +data will be passed into both sets of handlers. + +Raw links, as usual, do not have any processing performed. If they +contain query data, it will be passed on to their target as it would +for any link in any HTML document. + + +# Defining Situations in HTML + +*New in Version 2* + +From v.2, Undum supports defining situations entirely from HTML. The +tutorial game files show this in action, if you want to see a concrete +example. + +### Required Data + +Situations defined in HTML should be diven as a `div` with +`class="situation"` set. The content of the `div` will be turned into +a new `SimpleSituation` (see the API +document), with the content of the div output when the situation's +`enter` method is called. In addition to the `class="situation"` and +the HTML content, the `div` also requires its `id` attribute to be +set, and the value of this id will be used as the situation id for the +newly created situation. Situations created from HTML are instances of +the `SimpleSituation` prototype. + +The game scans the HTML file for situations, compiles them and adds +them to the main `game.situation` dictionary. Because the situations +end up in the same place, you can freely mix the two methods, defining +some situations in HTML, and others in Javascript. For this reason, +you can't have a situation defined in the HTML with the same id as one +in your Javascript file. This will raise an error. + +### Optional Data + +In addition to the id and content of the situation, additional options +can be set by defining one or more of the following `data-` attributes +on the `div`. Each is interpreted and passed to a corresponding option +on a `SimpleSituation` object, so to find more information on what +each value means, see the Javascript API. + +#### data-option-text + +If defined, this specifies the label that will be used when the +situation appears in an choice block. In Javascript, this can be +either fixed text, or a function. In the HTML API, only fixed text is +supported. + +#### data-can-view + +If defined, this should be the body of a function that will be +compiled and attached to the situation's canView method. The +content of this attribute will be wrapped with: + + (function(character, system, situation) { + ... HTML attribute ... + }) + +to make the final function. So, your definition should end with a +`return` statement. For example: + +
+ +This is intended to be similar to the way browsers function with event +handlers on HTML tags, such as `onClick`. The actual semantics are +difficult to replicate exactly, and there may be use-cases that are +impossible, but for most uses, this will do the right thing. + +#### data-can-choose + +If defined, this should be the body of a function that will be +compiled and attached to the situations canChoose method. See the +description of `canView`, above, for details of how the value in this +attribute is interpreted. + +#### data-priority + +If given, this is parsed as a number and set as the situation's +`priority` value. + +#### data-frequency + +If given, this is parsed as a number and set as the situation's +`frequency` value. + +#### data-display-order + +If given, this is parsed as a number and set as the situation's +`displayOrder` value. + +#### data-tags + +If given this should be a set of tags to label the situation with. The +string is split at commas, spaces and tabs. So "foo, bar cube +dock-trog" is parsed as four tags: "foo", "bar", "cube" and +"dock-trog". + +#### data-heading + +If given, then this heading will be used as the `heading` property for +the SimpleSituation. If no `data-option-text` is given, the heading +will also be used in choice blocks. + +#### data-choices + +If given, this should be a list of items to use in generating an +implicit set of situation choices, exactly as for the `choices` +property of `SimpleSituation`. The values of this list is parsed +exactly as for `data-tags`, above, splitting at commas, spaces and +tags. + +#### data-min-choices + +If `data-choices` is given, this value can also be specified. If so, +it is interpreted as an integer and passed to the `minChoices` option +of `SimpleSituation`. + + +#### data-max-choices + +If `data-choices` is given, this value can also be specified. If so, +it is interpreted as an integer and passed to the `maxChoices` option +of `SimpleSituation`. \ No newline at end of file diff --git a/en/README.md b/en/README.md new file mode 100644 index 0000000..ad0bd2e --- /dev/null +++ b/en/README.md @@ -0,0 +1 @@ +# Undum 2 documentation diff --git a/en/SUMMARY.md b/en/SUMMARY.md new file mode 100644 index 0000000..9d17609 --- /dev/null +++ b/en/SUMMARY.md @@ -0,0 +1,4 @@ +# Summary + +* [Javascript API](api.md) + diff --git a/en/api.md b/en/api.md new file mode 100644 index 0000000..a6da863 --- /dev/null +++ b/en/api.md @@ -0,0 +1 @@ +# Javascript API diff --git a/en/base.html b/en/base.html new file mode 100644 index 0000000..e85338b --- /dev/null +++ b/en/base.html @@ -0,0 +1,149 @@ + + + + + + +
+
+

Undum Documentation: {{title}}

+
+
+ +

Contents

+
    + {% for level,id,text in toc %} +
  • {{text}}
  • + {% endfor %} +
+
+
+ {{ content }} +
+ +
+ + diff --git a/en/creating.md b/en/creating.md new file mode 100644 index 0000000..4c7fce6 --- /dev/null +++ b/en/creating.md @@ -0,0 +1,263 @@ +# Creating an Undum Game + +# File Structure + +An Undum game consists of a single HTML file. This imports the game +engine and any supporting files. It also provides the structure needed +for Undum to place content correctly on-screen. + +The Undum engine consists of a single Javascript file, `undum.js`. In +order to work, however, it needs supporting files. It requires the +jQuery library (http://jquery.com) to be already imported, and it +requires a game definition file to be imported after it. + +The normal pattern of imports in the HTML file is therefore: + + + + + +By convention, the Javascript files are held in a `media/js` +directory, but this is not enforced, you can arrange these files as +you like, as long as you update the references to match. + +In addition to the Javascript files, Undum expects the HTML file that +imports it to have a particular structure. Although there is a good +deal of flexibility, if you need it, you should start with the HTML +file that is provided. + +Finally, the HTML file will include a CSS file that controls the look +and feel of the page. There are some elements in the CSS file which +are used by Undum, and so, as for the HTML page, you should start with +the CSS files provided. In most cases you will be able to leave the +CSS file untouched, or else just tweak colors and image imports to +match your game's style. + +## The HTML File + +The sample HTML file provided shows the key points to edit. They are: + +* The game's title. + +* The top-left panel title and summary (you can leave this as an + explanation of Undum, or change it to be more game-specific). + +* The copyright message. Please note that there is also a message + that acknowledges your game is based on Undum. You can remove this + entirely, but if you do leave it in place, that helps people + find the software and perhaps write their own game. + +* The path to your game definition file. By convention, game + definition files are named `yourgamename.game.js`. + +In addition, from v.2 onwards, Undum supports defining Situations +entirely within HTML. These situations are scanned and added to +Situations defined in your Javascript Game Definition file, allowing +you to have the best of both worlds. HTML Situations are discussed in +the page on the HTML API. + + +## The Game Definition File + +The game definition file where you create your game. To define a game +you must provide the following data: + +* A unique ID for the game, which is used to make sure saved games + don't get confused. + +* A version number that allows you to manage upgrades to your + content. + +* All the Situations that make up your game. + +* The identifier of the situation that starts the game. + +In addition it is very common to provide the following data: + +* Descriptions of each quality your game will use, and how that should + be displayed to the player. + +* Definitions of what groups of qualities should appear in the + character panel and what headings to use to label them. + +* An Initialization function that sets up the game ready for + playing. This is where you typically assign any starting qualities + to the character, or set their initial character text. + +And finally, there are a range of other data you can provide: + +* Functions to be called whenever any situation is entered, or exited. + +* Functions to be called before or after any action is carried out. + +### Identifiers + +Identifiers are small snippets of text that allow you to refer to +something in Undum. There are two types of identifier. The Game +identifier represents your whole game, and has its own particular +requirements (described below). + +Lots of other things in Undum have identifiers (Situations, Actions, +Qualities, Quality Groups), and they all have the same +requirements. These identifiers must consist of Latin lower-case +letters (i.e. a-z, no accents), hyphens, and the digits 0-9 only. + +### Game ID + +The game identifier should be a string that is unlikely to be used in +other games. You could use a UUID (my preference), or you could use a +variation on your email `mygame-myname@mydomain.com`, or a URL you +control `http://mydomain.com/undum-games/mygame`. If and when Undum +games end up being re-distributable (as I hope they will), having a +universally unique identifier will mean that saved games don't clash. + +As stated previously, the game identifier doesn't have the same +requirements as any other identifier in Undum, you can use any +characters to make up your game ID. + +### Version Number + +The version number is a string of text that indicates what version of +the content is in the file. There is no set format for this version +text, so you can use any scheme that suits you. I have used the +"major.minor" approach. + +Like the Game ID, this value is used to make sure that saved games +don't clash. If you change you content, then previous saved games may +not work correctly. By updating the version number, you allow the +player to be notified of this directly, rather than suffering a +silent crash. The effect of this is that you don't need to update the +version number if you make a change to something that doesn't alter +the structure of the game. If you just change some text, for example, +or add an extra action that merely outputs a piece of description. + +### Situation List + +Situations are defined in a Javascript object, placed in the +`undum.game.situations` property. Situations in the object use their +situation identifier as a property name, and a `Situation` object as +its value. For example: + + undum.game.situations = { + doorway: new Situation(...), + lobby: new SimpleSituation(...), + lobby-upstairs-closed: new MyCustomSituation(...), + ... etc ... + }; + +The situation objects are described more fully below. + +### Starting Situation + +This is placed in the `undum.game.start` property. It should consist +of the situation identifier as a string. It must be given. + +### Qualities + +Qualities don't have to be displayed to the user. They can just +function as internal properties for use by your code. Qualities that +will never be displayed don't need to be declared, you can just set +them when you need them (we'll look at the API for setting qualities +below). + +Often you want the quality to be displayed, however, and so you need +to tell Undum to display the quality, and how it should be +formatted. The `QualityDefinition` object does that. Any quality that +doesn't have a corresponding quality definition will be invisible to +the player. + +Quality definitions are placed in an object in the +`undum.game.qualities` property. Within this object, the property +names are the quality identifiers, and the values they contain are +`QualityDefinition` objects. For example: + + undum.game.qualities = { + investigation: new IntegerQuality("Investigation", ...), + "found-mr-black": new OnOffQuality("Found Mr. Black", ...), + ... etc ... + }; + +There are a number of `QualityDefinition` constructors defined which +automatically format in common ways, you can also define your own and +take complete control of the output. We'll return to discussion of the +API, below. + +### Quality Groups + +Qualities can be assigned to groups, and displayed under a common +heading in the character panel. To define groups, place an object in +the `undum.game.qualityGroups` property. This object should have +properties which are the group identifiers, and values that are +`QualityGroup` objects. For example: + + undum.game.qualityGroups = { + stats: new QualityGroup(...), + clues: new QualityGroup(...), + equipment: new QualityGroup(...) + } + +A common source of puzzlement is that you don't use this data +structure to define which qualities belong in which group. Instead, +each quality that you want to assign to a group, should be given the +identifier of the group it belongs to. So your `undum.game.qualities` +property will look something like: + + undum.game.qualities = { + investigation: new IntegerQuality("Investigation", {group:'stats'}), + "found-mr-black": new OnOffQuality("Found Mr. Black", {group:'clues'}), + ... etc ... + }; + +Again, see the API documentation below for more details about what you +can pass into these constructors. + +### Initialization Function + +Your initialization function should be placed in the `undum.game.init` +property. Normally its job is to configure the character at the start +of the game. For example: + + undum.game.init = function(character, system) { + character.qualities.investigating = 0; + character.qualities.money = 100; + ... etc ... + system.setCharacterText(...); + }; + +Initialization functions can, but normally doesn't, output +text. Instead the starting situation is tasked with outputting the +initial content. + +### Global Event Functions + +Most of the time you want Situations to handle user +interaction. Occasionally, however, you have to handle something that +spans situations. It would be inconvenient to duplicate the same code +in every situation. So Undum provides a set of hooks for you to +respond globally to user interaction. There are five of these: +`enter`, `afterEnter`, `exit`, `beforeAction` and `afterAction`. You +can define functions in your game file using the properties: +`undum.game.enter`, `undum.game.afterEnter`, +`undum.game.exit`, `undum.game.beforeAction`, and +`undum.game.afterAction`. + +The `enter`, `afterEnter`, and `exit` functions look like this: + + undum.game.enter = function(character, system, from, to) { + ... + }; + +where `from` and `to` are the identifiers of the situations being left +and entered, respectively. And the `beforeAction` and `afterAction` +functions look like this: + + undum.game.beforeAction = function(character, system, situation, action) { + ... + }; + +where `situation` is the current situation identifier, and `action` is +the identifier of the action being carried out. + +These functions intentionally look like the `enter`, `exit` and `act` +methods of the `Situation` object. These are described in more detail +in the API reference. diff --git a/en/files.md b/en/files.md new file mode 100644 index 0000000..518eea5 --- /dev/null +++ b/en/files.md @@ -0,0 +1,80 @@ +# Loading and Saving + +# Loading and Saving + +There is no API for you to manually access loading and saving +functionality. The load and save functions are triggered by the +buttons on the user interface. But the way loading and saving work +does have a big impact on the way you write your code. + +Undum makes a big feature of the fact that you can scroll back through +the story you've helped create. To save your character's progress you +would have to save not only the current situation and the character's +qualities, but also all the text that has been generated up to that +point. This would not be a problem in a downloaded game, because your +hard-drive is plenty big enough. Unfortunately in a browser game, +there is a limit on how much data you can store. Worse, this data +limit is per-domain. So if you hosted 10 Undum games on a server, the +saved games from all ten would have to fit into the limited +space. This makes it impractical to save the complete text history. + +Instead Undum saves all the actions you've taken as a player. It +doesn't save the character's qualities or any other information, just +the actions. It expects to be able to rebuild the complete text, and +the complete current state of the character, by playing back these +actions when the file is loaded. We call this determinism, because the +current state of the character and the content needs to be determined +from just the actions they take. + +# Writing with Saving / Loading in Mind + +This means that you must take care to write all your code in a way +that will generate *exactly* the same results if the game was played +again in the same way. + +There are two major limitations to this, firstly it means you can't +use random events, and secondly you can't use timed events. Both of +these are such serious limitations that Undum provides ways around +them. + +If you do not follow these restrictions, then it is likely that saved +games will not load correctly. A player may save their game at one +point and find most of their progress wiped out when they load it +again. + +## Random Numbers + +Undum provides your code with a random number generator in +`System.rng`, which is an object with the prototype `Random`. This +random number generator works with the loading and saving code to make +sure that, when you load a saved game, the exact same random number +requests will produce the exact same result. This means you get all +the benefits of randomness (i.e. two separate games may have different +results for the same action), but we can always replay a game +exactly. Dealing with random actions is a difficult issue in testing +any interactive fiction game. This approach solves that problem. You +should, therefore, *never* use Javascript's built-in random number +generate (`Math.random`), only ever use the one provided by Undum. + +## Timing + +Finally, Undum also provides your code timing information in +`System.time`, which is the number of seconds (and fractional seconds) +elapsed since the player began the game. You can use this timing +information to implement puzzles in your game (such as asking the +player to complete a series of tasks in a specified amount of +time). This timing system coordinates with the loading and saving +system to make sure that, when you save and load the game, the timing +picks up where it left off. Feel free to make decisions in your code +based on the current value of `System.time`, but never use +Javascript's `Date` object. + +## Detecting Replay When Loading + +If your game has elements that should not be triggered while Undum is +replaying a saved game, for example sound effects or popup notifications, +you can use `undum.isInteractive()` to test whether the game is being +played normally (returns `true`) or being loaded from a save game +(returns `false`). + + diff --git a/en/i18n.md b/en/i18n.md new file mode 100644 index 0000000..e3beeb1 --- /dev/null +++ b/en/i18n.md @@ -0,0 +1,98 @@ + +# Translation and Internationalization + +Undum provides support for translations and internationalization. +In particular, if you feel you want to translate Undum, then a lot +of work has already been done for you. I am very grateful to Oreolek +for this assistance. He translated the Russian version within days +of the code being released, and advised on the tools that would +make translation easier. + +To write a game in another language, you need only to write the game +content in that language. The identifiers you use in the game (to +represent situations, actions, qualities and quality groups) must use +only unaccented lower case latin letters and numbers, but the text you +generate can contain any content you choose. Including right to left +content or ideographs. + +Undum itself has a small number of error messages and pieces of text +that it uses. These include the default names for the +FudgeAdjectivesQuality values. These strings are all found at the end +of the `undum.js` file. They can be overridden. Simply define a new +language file for your language (e.g. `lang/gk.js`) and override the +appropriate strings. In your HTML file, after importing `undum.js`, +import you strings file. For example, the end of the Russian +translation of the tutorial (`tutorial.ru.html`) has: + + + + +These translation strings are given as an object mapping the string +name to the translated strings. This object is given as part of the +`undum.translation` object, with a property name equal to the language +name. So, for example, the UK English translation might begin: + + undum.lanuage["en-UK"] = { + no_group_definition: "Couldn't find a group definition for {id}.", + +Within the translation strings, data to be incorporated later is given +in curly braces. + + +## Language Codes + +Undum uses a simplified version of the IETF standards for language +code. For our purposes this consists of three parts, only the first of +which is required: `language-Script-REGION` where `language` is a two +letter lower-case ISO language code, `Script` is a four letter +title-case script identifier, and `REGION` is a two letter country or +region code, all capitalized. The script is omitted when it is the +default script for a language and locale. You would specify a script +if you were using romaji (Latin letters) to write Japanese, but not if +you were writing it in Kanji and kana. + +The major virtue of this standard is that it allows fall through when +a translation is not available. For example a translation into +Brazillian Portuguese `pt-BR` might be different to one into Angolan +Portuguese `pt-AO`, but there may be some strings they have in +common. This allows a translator to create a base file for just plain +Portuguese `pt`, then each country's dialect can define its own file +that just overrides a few of the strings. + + +## Filename Conventions + +It is only a convention, but for all files that occur in language +specific versions, I have used the filename convention of placing the +language code before the extension, e.g. `filename.lang.extension`. The +game file is similar `filename.game.lang.js`. You are free to use any +format you choose, of course, but if you want to contribute back to +the trunk, please follow this convention, to save having to rename +things and connect up the links later. + + +## API + +The translation system provides a simple API based on the `Globalite` +package of Nicolas Merouze (the implementation is unique to Undum). It +adds a `l()` method to the Javascript `String` prototype. This method +has the signature `l(data)`, where data can be any object mapping +strings to other strings. + +The method attempts to figure out what the current language is by +looking at the `lang` attribute of the top level HTML tag (you'll +notice in the tutorial games this is defined in all cases, you should +do the same). It then tries to find a matching object containing +translations in `undum.language`. If it finds such an object, then it +looks up the original string in that object to find a translation. It +then merges any data passed into the `l` method into the string, +before returning the result. + +The translation look-up honors the IETF rules for language fallback, +so (continuing the previous example) if your game file is in Brazilian +Portuguese `pt-BR`, and a translation isn't found, then generic +Portuguese translation `pt` is also checked. Finally, if no valid +translation is found, then the default version is used. Since Undum +was written in English, this default version is the English +version. This is purely by my convenience, and isn't part of the IETF +spec! diff --git a/en/implicit.md b/en/implicit.md new file mode 100644 index 0000000..046b6dc --- /dev/null +++ b/en/implicit.md @@ -0,0 +1,204 @@ +# New Choice System + +# New Choice System + +*New in Version 2* + +In version one of Undum, all links from one situation to another had +to be created manually using HTML. If you wanted a set of choices to +offer, you had to create the links yourself, put them in the +appropriate HTML container. If you wanted those choices to depend on +the current state of the game (say, a choice to look behind a secret +panel that was only visible when the panel was discovered), you had to +code that logic yourself in HTML. This meant that, in practice, most +Undum games were simpler, and rarely used branches that depended on +context. + +In version 2 both of these issues were addressed: the ability to +quickly build the links to new situations in the standard HTML format +(using the `System.writeChoices` method), and the ability to generate +a list of situations that are available, given the current state of +the game. + +# Generating Choice HTML + +Thew new `System.writeChoices` method allows you to give a list of +situation id's and have Undum generate a standard looking block of +choices. + +It does this by asking each choice how it prefers to be displayed, by +calling its `optionText` method. This allows situtions to change how +they are displayed depending on the current state of the character. + +Also called is the situations `canChoose` method. This will normally +return true, but if it returns false, the option will still be +displayed, but not as a link, and will not be clickable. This allows +you to show the player that an option would be available, if they did +something else first, such as increase a quality. + +On its own `System.writeChoices` is still mostly manual: it finds the +link text for you, and builds the HTML, but you still have to give it +a set of situation ids that you want for your choices. + +# Generating Choices + +Undum now also provides the `System.getSituationIdChoices` method +which automatically compiles a list of situation ids, which can then +be passed to `System.writeChoices` for display. This method is +powerful and complex, so we'll explore its use in increasing depth. + +## Generating Choices by Tags + +Situations now can have one or more tags associated with them. You can +ask `System.getSituationIdChoices` to return the ids of any situtions +that match a tag. This allows you to easily build decisions that you +can extend later. You might have a 'chapter' tag, and you mark each +situation which begins a chapter using this tag, you can then do. + + system.getSituationIdChoices(['#chapter']) + +to return all chapter choices. + +The way tags are processed tries to be intelligent. You can match on +more than one tag, and any situation matching either tag will be +returned, but each situation will be returned no more than once. You +can even mix tags and explicit situation ids: + + system.getSituationIdChoices(['#chapter', 'introduction', '#endmatter']) + +When you only need to pass one tag to `System.getSituationIdChoices` +you can do so without using a list, so the first example above could +be equally written: + + system.getSituationIdChoices('#chapter') + + +## Ordering Choices + +Choices returned by `System.getSituationIdChoices` will be ordered +based on a new `displayOrder` numeric property of situations. This +allows you to make sure situations appear in a logical order, +regardless of whether they were selected by id or by tag. + + +## Conditional Appearance + +So far, any matched situation will always be featured in the list of +choices. A situation can't be visible some times and not others, +depending on the current state of the game. (As we saw with the +`canChoose` method, we can have it be clickable only in some states). + +To allow situations to be totally absent in some cases, there is a new +`canView` method on situations. This is only used by +`system.getSituationIdChoices`, and allows a situation to opt out of +being included, if its conditions for appearance are not met. This +allows us to implement the secret panel from the introduction. + +We could have a 'go-to-the-basement' situation with tag +'from-the-hallway' available always, while 'go-to-the-secret-room' has +the tag 'from-the-hallway', but a canView method: + + secretRoomSituation.canView = function(character, system, host) { + return character.sandbox.has_found_secret_panel; + } + +We can then call `system.getSituationIdChoices(['#from-the-hallway'])` +and have the correct choices displayed, depending on the current state +of the game. + + +## Priority + +One common requirement is to have a set of choices which can be +'overrulled' if some condition is true. So we might want the player to +choose where on the island to go to, but if the character is injured, +we might want to only allow the character to go to the hospital. + +By default, all situations have a priority of 1. If you give a +situation a higher priority, then it will be considered first. If its +`canView` method returns true, then the high priority situation will +be the only one displayed. + +So the injury example might have + +- Docks tag:location canView:always priority:1 +- Market tag:location canView:always priority:1 +- Hospital tag:location canView:when hits < 10 priority:2 +- Doctor tag:location canView:when hits < 10 priority:2 + +Then if the hits quality = 10, we'd see + +- Docks +- Market + +but if the hits quality dropped to 9, we'd see just + +- Hospital +- Doctor + +Note that any number of results can be displayed in both cases, but +the higher priorities mask the lower ones. + +If you are working with choices that all have a canView function, it +is a good idea to have a 'fallback' situation that can always be +viewed, but has a priority of zero. This will only be visible if none +of the others are available, and will prevent the game from ending at +that point. + + +## Maximum Choices + +When you ask for a list of choices, you can specify a maximum number +to return. If more than this number of choices are available, then the +system will select a random subset to return, to make sure you get the +number you asked for. + +By default, all matching situations are equally likely to be returned, +but you can make some situations rarer or more common by setting their +`frequency` value. By default, this value is 1 for a situation. + +A situation with a frequency of 100 will be chosen 100 times more +often than a situation with a frequency of 1, if there is one +situation that needs selecting. In cases where more than one situation +needs chosing, the frequencies are a little less intuitive. + +Consider three situations with frequencies of 1, 1, 100, competing for +two spaces. The 100-frequency situation will be chosen almost every +time, but for the other space, one of the 1-frequency situations must +be chosen. So the actual probabilities will be roughly 50%, 50%, 100%, +even though the frequencies were 1, 1, 100. When selecting more than +one result, frequencies can only be a guide. + + +## Minimum Choices + +Although rarely used, you can also ask for a minimum number of +choices. This changes the way priority values work. It starts from the +highest priority situations, as normal, but rather than returning only +those at the highest priority level, it checks to see if that set is +enough to meet its minimum. If not, then the next priority level down +will be considered as well, and so on, until the minimum is reached. + +If a minimum and a maximum is given (the maximum being at least as +large as the minimum), then only the lowest priority situations will +be randomly selected for any remaining spaces, higher priority +situations will be guaranteed to be chosen. + +The most common use of this parameter is to set a very high value, +such as Number.INT_MAX, with no maximum limit. This ensures that all +valid situations are returned, regardless of their priority level. + + +## Choices and SimpleSituation + +`SimpleSituation` provides built-in support for ending its content +with a block of choices, using `System.getSituationIdChoices` to +generate the list and `System.writeChoices` to generate the HTML. To +use this, simply pass in the list of ids and tags as the `choices` +option. You can additionally specify `minChoices` and `maxChoices` if +you need them. + +As for `System.getSituationIdChoices`, if you are only using a single +tag or id, you can give this as a string, rather than a single element +list. + diff --git a/en/index.md b/en/index.md new file mode 100644 index 0000000..ae3f1c6 --- /dev/null +++ b/en/index.md @@ -0,0 +1,71 @@ +# Home + +# Contents + +## High level overview + +Describes the concepts that go into an Undum game, and how they +interact. + +## Creating an Undum Game + +Describes the files you need to create to make an Undum game, and what +needs to go into them. + +## Implicit Choices + +Version 2 of Undum includes a new framework for automatically +generating choices for the player, based on information stored in +situations. + +## HTML API + +Undum games use HTML to output text and media, but has some +constraints on the HTML you can use. Undum also provides built-in +behavior tied to specific HTML classes that you can use in your +output. In v.2, Undum also added support for defining many kinds of +situation entirely in HTML, with no Javascript needed. + +## Javascript API + +A complete breakdown of the API exposed to your code via +Javascript. This details the methods that you call to output content, +find random numbers and translate your game. + +## Translation and Internationalization + +Describes Undum's core translation system, and how you can create +games that support multiple languages. + +## Loading and Saving + +Undum has an unusual way of supporting loading and saving of games, to +support a wide range of browsers, sites and game styles. This document +contains the technical details, and how this affects you as a game +author. + + +# Undum Changelog + +## 2011-05-27 + +- Added `System.writeBefore` to do out of order insertion. (credit: + ekyrath) + +- Added an optional selector to `System.write` and + `System.writeBefore` to support out of order insertion. (credit: + ekyrath) + +- Removed the use of `__defineGetter__`, so that the core code now + works on IE7 (thanks for the bug report juhana and bloomengine). + +## 2011-08-18 + +- Added support for functions in the `content` and `header` of a + `SimpleSituation` (credit: David Eyk). + +## 2013-09-27 + +- Updated to v.2, including support for implicit choices and HTML-defined situations. \ No newline at end of file diff --git a/en/introduction.md b/en/introduction.md new file mode 100644 index 0000000..601e6a5 --- /dev/null +++ b/en/introduction.md @@ -0,0 +1,54 @@ +# Introduction + +# High Level Overview + +Undum games are based around three concepts: Situations, Actions and +Qualities. + +## Situations + +A situation is a chunk of code that is responsible for adding content +to the screen and responding to user interaction. All user interaction +is performed by clicking links in the content. + +Often a link will change the current situation, in which case another +situation is loaded, can write to the screen, and can begin responding +to user interaction. When a situation changes, all links that were +previously available are removed, so that the player can't unfairly go +back and try alternative options after committing to one. It is +possible to override this behavior, see the section on 'Sticky', +below. + +There is always exactly one active situation. These situations, and +the links between them, form the structure of the game. + +## Actions + +A situation may offer the player a series of actions to perform. These +actions are internal to that situation and normally do not cause the +situation to change. Actions may output more content, including new +links for the user to select. + +## Qualities + +Qualities represent the current state of the character. Internally +they are all numeric values, able to take on any decimal value, +positive or negative. They have no meaning to Undum - they are given +meaning by your code as you perform calculations or make decisions +based on their value. + +Qualities display themselves to the user through a formatting +function, which can turn the number into any kind of indicator: a +progress bar, a symbol, a word, an integer, and so on. So as far as +the user is concerned, qualities can represent any kind of value. + +## Other Concepts + +There are a handful of other elements to an Undum game, but they are +very much in a supporting role. Quality groups allow you to display a +set of qualities under a common heading; and character text is a short +chunk of HTML that you can use to summarize a character's qualities, +or to give hints. + + + diff --git a/ru/README.md b/ru/README.md new file mode 100644 index 0000000..cc3b2cd --- /dev/null +++ b/ru/README.md @@ -0,0 +1 @@ +# Документация Undum 2 diff --git a/ru/SUMMARY.md b/ru/SUMMARY.md new file mode 100644 index 0000000..9d17609 --- /dev/null +++ b/ru/SUMMARY.md @@ -0,0 +1,4 @@ +# Summary + +* [Javascript API](api.md) + diff --git a/ru/api.md b/ru/api.md new file mode 100644 index 0000000..a6da863 --- /dev/null +++ b/ru/api.md @@ -0,0 +1 @@ +# Javascript API