modid.t | documentation |
#charset "us-ascii" /* * Copyright (c) 2000, 2006 Michael J. Roberts. All Rights Reserved. * * adv3Lite Library - module ID's * * This module defines a framework for "module ID's." The module ID * mechanism allows library modules to identify themselves. The module * ID framework is modular, in that several libraries can be linked * together without any prior knowledge of one another, and the module ID * framework will be able to find all of their ID's. */ /* include the library header */ #include "advlite.h" /* we also require file access */ #include <file.h> /* ------------------------------------------------------------------------ */ /* * Module ID. Each library add-in can define one of these, so that the * "credits" command and the like can automatically show the version of * each library module included in the finished game, without the game's * author having to compile a list of the module versions manually. * * An easy way to implement a CREDITS command is to define a ModuleID * object for the game itself, and override the showCredit() method to * display the text of the game's credits. The module object for the * game itself should usually have a listingOrder of 1, because the * author usually will want the game's information to be displayed first * in any listing that shows each included library module (such as the * VERSION command's output). */ class ModuleID: object /* my name */ name = '' /* the "byline" for the module, in plain text and HTML versions */ byline = '' htmlByline = '' /* my version number string */ version = '' /* * Show my library credit. By default won't show anything. * Libraries should generally not override this, because we want to * leave it up to the author to determine how the credits are * displayed. If a library overrides this, then the author won't be * able to control the formatting of the library credit, which is * undesirable. */ showCredit() { } /* * Show version information. By default, we show our name and * version number, then start a new line. The main game's module ID * should generally override this to show an appropriate version * message for the game, and any library add-ins that want to * display their version information can override this to do so. */ showVersion() { showVersionMsg(name, version); "\n"; } showVersionMsg(nam, ver) { DMsg(show version, '{1} version {2}', nam, ver); } /* * Show the "about this game" information. By default, we show * nothing here. Typically, only the game's module ID object will * override this; in the game's module ID object, this method should * display any desired background information about the game that * the author wants the player to see on typing the ABOUT command. * * The ABOUT command conventionally displays information about the * game and its author - the kind of thing you'd find in an author's * notes section in a book - along with any special instructions to * the player, such as notes on unusual command syntax. Information * that players will find especially helpful include: * * - A list of any unusual command phrasings that the game uses. * Ideally, you will disclose here every verb that's required to * complete the game, beyond the basic set common to most games * (LOOK, INVENTORY, NORTH, SOUTH, TAKE, DROP, PUT IN, etc). By * disclosing every necessary verb and phrasing, you can be certain * to avoid "guess the verb" puzzles. (Note that it's possible to * disclose every *required* verb without disclosing every * *accepted* verb - some verbs might be so suggestive of a * particular puzzle solution that you wouldn't want to disclose * them, but as long as you disclose less suggestive alternatives * that can be used to solve the same puzzles, you have a valid * defense against accusations of using "guess the verb" puzzles.) * * - A quick overview of the NPC conversation system, if any. * Conversation systems have been slowly evolving as authors * experiment with different styles, and at least three or four * different conventions have emerged. The default that experienced * players will expect is the traditional ASK/TELL system, so it's * especially important to mention your system if you're using * something else. * * - An indication of the "cruelty" level of the game. In * particular, many experienced players find it helpful to know from * the outset how careful they have to be about saving positions * throughout play, so it's helpful to point out whether or not it's * possible for the player character to be killed; whether it's * possible to get into situations where the game becomes * "unwinnable"; and if the game can become unwinnable, whether or * not this will become immediately clear. The kindest games never * kill the PC and are always winnable, no matter what actions the * player takes; it's never necessary to save these games except to * suspend a session for later resumption. The cruelest games kill * the PC without warning (although if they offer an UNDO command * from a "death" prompt, then even this doesn't constitute true * cruelty), and can become unwinnable in ways that aren't readily * and immediately apparent to the player, which means that the * player could proceed for quite some time (and thus invest * substantial effort) after the game is already lost. * * - A description of any special status line displays or other * on-screen information whose meaning might not be immediately * apparent. */ showAbout() { } /* * My listing order. When we compile a list of modules, we'll sort * the modules first by ascending listing order; any modules with * the same listing order will be sorted alphabetically by name with * respect to the other modules with the same listing order. * * The value 1 is reserved for the game's own ID object. Note that * the TADS 3 library defines a module ID with listing order 50, * which is chosen so that the main library credit will appear after * the game credits but before any extension credits using the * default order value 100 that we define here. Extensions are * free, however, to use a number lower than 5 if they wish to * appear before the main library credit. */ listingOrder = 100 /* * get a list of all of the modules that are part of the game, * sorted in listing order */ getModuleList() { local lst; /* compile a list of all of the modules */ lst = new Vector(10); forEachInstance(ModuleID, { obj: lst.append(obj) }); lst = lst.toList(); /* * sort the list by listing order (and alphabetically by name * where listing orders are the same) */ lst = lst.sort(SortAsc, function(a, b) { /* if the listings order differ, sort by listing order */ if (a.listingOrder != b.listingOrder) return a.listingOrder - b.listingOrder; /* the listing orders are the same; sort by name */ if (a.name < b.name) return -1; else if (a.name > b.name) return 1; else return 0; }); /* return the sorted list */ return lst; } ; /* ------------------------------------------------------------------------ */ /* * A module ID with metadata. During pre-initialization, we'll * automatically write out a file with the metadata for each of these * objects. This is an abstract base class; a subclass must be created * for each specific metadata format. */ class MetadataModuleID: ModuleID, PreinitObject /* execute pre-initialization */ execute() { /* write out our metadata */ writeMetadataFile(); } /* * write our metadata file - this must be overridden by each * subclass to carry out the specific steps needed to create and * write the metadata file in the appropriate format for the * subclass */ writeMetadataFile() { } ; /* * A module ID with GameInfo metadata. The GameInfo metadata format is * the standard TADS format for descriptive data about the game. The * usual way to use GameInfo metadata is to create a file called * "gameinfo.txt" for a game, then embed this file directly in the * game's .t3 file using the TADS 3 resource bundler (t3res). Once the * gameinfo.txt is embedded in the .t3 file, tools will be able to read * the game's descriptive data directly from the .t3 file. For example, * HTML TADS on Windows can read the information into its Game Chest, * which allows the interpreter to show the full name of the game, the * author, and a blurb describing the game, among other things. */ class GameInfoModuleID: MetadataModuleID /* * The IFID - this is a UUID uniquely identifying the game, using the * standard UUID format (xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where * each 'x' is a hexadecimal digit). You should pick an IFID when * you start each game project, and then keep the same IFID * throughout the game's entire existence, *including* version * updates. Each new version release of the same game - even major * new versions - should use the same IFID, so that the versions can * all be related to one another as the same game. * * If the game has multiple IFIDs, list them here, separated by * commas. You should NOT *intentionally* create multiple IFIDs for * your game; once you've created an IFID, it should be the unique * and permanent identifier for the game. In particular, do NOT * create a new IFID for a new version: the whole series of releases * throughout a game's lifetime should be identified by a single * IFID, so that archivists will know that the versions are all * incarnations of the same work. * * The reason that multiple IFIDs are allowed at all is that many * older games were not assigned explicit UUID-style IFIDs when * released. In such cases, the game has an "implied" IFID based on * an MD5 hash of the compiled game file's contents. Every release * that doesn't contain an explicit IFID will therefore have a * different implied IFID. So, for example, if you've already * released versions 1, 2, and 3 of your game, and you didn't assign * explicit IFID values to those releases, each version will have a * different implied IFID. When you release version 4, you should * NOT assign a new UUID-style IFID. Instead, in the IFID string * here, list ALL THREE of the implied IFIDs from the past releases. * Each of the three IFIDs counts from now on as an IFID for the * work, for all versions collectively. (By placing the list of * IFIDs in version 4, you prevent version 4 from adding yet another * implied IFID of its own: the explicit IFID list supersedes the * implied IFID.) See the Babel spec for more information, and for * instructions on how to calculate the implied IFID for a TADS game * that was released without a UUID-style IFID. */ IFID = '' /* * The game's headline. It's become an IF tradition to use a * quasi-subtitle of the sort that Infocom used, of the form "An * Interactive Mystery." This can be used to define that subtitle. */ headline = '' /* * If this game is part of a series, such as a trilogy, these can be * used to identify the name of the series and the position in the * series. The series name should be something like "The Enchanter * Trilogy"; the series number, if provided, should be a simple * integer string ('1', '2', etc) giving the position in the series. * Note that the series number isn't required even if a series name * is specified, since some series are just groups of works without * any particular ordering. */ seriesName = '' seriesNumber = '' /* * The genre of the game. Some games don't fit any particular genre, * and some authors just don't like the idea of having to pigeonhole * their games, so feel free to leave it out. If there's a good fit * to a well-established genre, though, you can specify it here. We * recommend you keep this short - one word, maybe two - and use a * genre name that's generally recognized as such. You might want to * use Baf's Guide as a reference (http://www.wurb.com/if/genre). */ genreName = '' /* * The forgiveness level, according to the Zarfian scale propounded * by Andrew Plotkin on rec.arts.int-fiction. This must be one of * these terms, using the exact capitalization shown: Merciful, * Polite, Tough, Nasty, Cruel. */ forgivenessLevel = '' /* * The names and email addresses of the authors, in GameInfo format. * This list must use the following format: * * author one <email>; author two <email> <email>; ... * * In other words, list the first author's name, followed by one or * more email addresses, in angle brackets, for the first author. * If more than one author is to be listed, add a semicolon, * followed by the name of the second author, followed by the second * author's email address or addresses, enclosing each in angle * brackets. Repeat as needed for additional authors. The list * does not need to end with a semicolon; semicolons are merely used * to separate entries. */ authorEmail = '' /* * The game's web site, if any. If specified, this must be an * absolute URL with http protocol - that is, it must be of the form * "http://mydomain.com/...". */ gameUrl = '' /* * Descriptive text for the game, in plain text format. This is a * short description that can be used, for example, in a catalog of * games. This should be a couple of sentences or so. */ desc = '' /* * Descriptive text for the game, as an HTML fragment. This should * have the same information as the 'desc', but this version can use * HTML markups (including tags and character entities) to embellish * the display of the text. Any HTML markups should be "in-line" * body elements only, not "block" or head elements, so that this * text can be inserted into a larger HTML document. For example, * markups like <i> and <b> are fine, but <p> and <table> should not * be used. */ htmlDesc = '' /* * The release date. By default, we compute this statically to be * today's date. This means this will be set to the date of * compilation. If the game wishes to override this, note that the * GameInfo format requires this to be of the form YYYY-MM-DD. For * example, December 9, 2001 would be '2001-12-09'. */ releaseDate = static getGameInfoToday() /* * The date of first publication. This can be just a year in YYYY * format, or a full YYYY-MM-DD date. This is the original release * date of the original version of the game, which is often of * interest to archivists. This should *not* be updated when a new * release is made - it's always the date of *original* publication. */ firstPublished = '' /* * The language in which this game's text is written. This is the * RFC3066 language code for the main language of the work. For * example, games written in US English would use 'en-US', while * games written in British English would use 'en-GB'. Note that * each language-specific library module should use 'modify' to set * this to the default for the library. */ languageCode = '' /* * The license type for this game. Most text IF games these days * are released as freeware, so we use this as the default. The * GameInfo metadata format defines several other standard license * types, including Public Domain, Shareware, Commercial Demo, * Commercial, and Other. Authors should change this if they plan * to release under a licensing model other than freeware. * * Note that the GameInfo metadata format documentation explicitly * states that the license type indicated here is advisory only and * cannot be considered definitive. This means that this setting * does not take away any of the author's rights to set specific * license terms. Even so, we recommend that you pick an * appropriate value here to avoid any confusion. */ licenseType = 'Freeware' /* * The copying rules for this game. Most text games these days are * released as freeware with minimal restrictions on copying, so we * use a default of "nominal cost only." Other values defined in the * GameInfo format include Prohibited, No Restrictions, No-Cost Only, * At-Cost Only, and Other. A modifier indicates whether or not the * game may be included in compilations (such as those "10,001 great * games" CD-R's that people like to sell on auction sites); we * indicate that inclusion in compilations is allowed by default. * You can change this to "Compilations Prohibited" if you prefer not * to allow your game to be distributed in that fashion. * * Note that the restrictions specified here aren't enforced by any * sort of copy-protection or DRM (digital rights management) * technology. This information is entirely for the benefit of * conscientious users who want to abide by your wishes and thus need * to know what your wishes are. * * The GameInfo bundle is mostly for the benefit of software that can * extract the information from the compiled game. So, we recommend * that you also put a full notice and explanation of your license * restrictions somewhere that users can easily find it, such as in a * separate LICENSE.TXT file that you distribute with your game, or * in the text of the game itself (displayed by a LICENSE or * COPYRIGHT command, for example). */ copyingRules = 'Nominal cost only; compilations allowed' /* * The recommended "presentation profile" for the game. 'Default' * means that the interpreter's default profile should be used. * (Some interpreters let the user select which profile to use as the * default, in which case 'Default' means we'll use that profile.) */ presentationProfile = 'Default' /* write our metadata file */ writeMetadataFile() { local f; /* * open the file - note that the GameInfo.txt resource is * required to be encoded in UTF-8, so open the file with the * UTF-8 character set */ f = File.openTextFile(gameInfoFilename, FileAccessWrite, 'utf-8'); /* scan our list of metadata keys and write each one */ for (local i = 1, local len = metadataKeys.length() ; i + 1 <= len ; i += 2) { local key; local prop; local val; /* get the key name and value property for this entry */ key = metadataKeys[i]; prop = metadataKeys[i+1]; val = self.(prop); /* turn any '\ ' characters into ' ' characters */ val = val.findReplace('\ ', ' ', ReplaceAll); /* write out this key if there's a value defined for it */ if (val != nil && val != '') f.writeFile(key + ': ' + val + '\n'); } /* done with the file - close it */ f.closeFile(); /* remember the primary IFID in the globals */ libGlobal.IFID = rexReplace([',.*$', '<space>+'], IFID, ''); } /* * the GameInfo filename - by default, we write the standard * gameinfo.txt file */ gameInfoFilename = 'GameInfo.txt' /* * The metadata key mappings. This is a list of key/property pairs. * The key in each pair is a string giving a standard GameInfo key * name, and the property gives the property (of self) that we * evaluate to get the string value for that key. */ metadataKeys = [ 'IFID', &IFID, 'Name', &name, 'Headline', &headline, 'Byline', &byline, 'HtmlByline', &htmlByline, 'AuthorEmail', &authorEmail, 'Url', &gameUrl, 'Desc', &desc, 'HtmlDesc', &htmlDesc, 'Version', &version, 'ReleaseDate', &releaseDate, 'FirstPublished', &firstPublished, 'Series', &seriesName, 'SeriesNumber', &seriesNumber, 'Genre', &genreName, 'Forgiveness', &forgivenessLevel, 'Language', &languageCode, 'LicenseType', &licenseType, 'CopyingRules', ©ingRules, 'PresentationProfile', &presentationProfile ] /* * get today's date, using the GameInfo standard date format * (YYYY-MM-DD) */ getGameInfoToday() { local dt; local mm, dd; /* get the current date */ dt = getTime(GetTimeDateAndTime); /* get the month, and add a leading zero if it's only one digit */ mm = (dt[2] < 10 ? '0' : '') + dt[2]; /* get the day, and add a leading zero if it's only one digit */ dd = (dt[3] < 10 ? '0' : '') + dt[3]; /* build and return the full YYYY-MM-DD date string */ return toString(dt[1]) + '-' + mm + '-' + dd; } ; /* ------------------------------------------------------------------------ */ /* * Base class for the game's module ID. This merely sets the listing * order to 1 so that the game's credit is listed first. Normally, * exactly one GameID object, called 'versionInfo', is defined in a game, * to provide the game's identifying information. * * Note that this class is based on GameInfoModuleID, so the library will * automatically write out a gameinfo.txt file based on this object's * settings. For full GameInfo data, the game should minimally define the * following properties (see GameInfoModuleID and ModuleID for details on * these properties): * *. IFID - a random 32-digit hex number to uniquely identify the game; *. you can generate one at http://www.tads.org/ifidgen/ifidgen *. name - the name of the game *. byline - the main author credit: "by so and so" *. htmlByline - the main author credit as an HTML fragment *. authorEmail - the authors' names and email addresses (in GameInfo format) *. desc - a short blurb describing the game, in plain text format *. htmlDesc - the descriptive blurb as an HTML ragment *. version - the game's version string * * In addition, you can override the following settings if you don't like * the defaults inherited from GameInfoModuleID: * *. releaseDate - the release date string (YYYY-MM-DD) *. licenseType - freeware, shareware, etc. *. copyingRules - summary rules on copying *. presentationProfile - Multimedia, Plain Text */ class GameID: GameInfoModuleID /* always list the game's credits before any library credits */ listingOrder = 1 /* * Show the game's credits. By default, we'll just show our name and * by-line. * * Typically, authors will want to override this to display the full * credits for the game. Most authors like to show the author or * authors, along with notes of thanks to important contributors. * * Note that libraries generally will not show anything automatically * in the credits, to allow the author full control over the * formatting of the credits. Authors are encouraged to give credit * where it's due for any libraries they use. */ showCredit() { /* by default, just show the game's name and by-line */ gLibMessages.showCredit(name, htmlByline); } /* * show a blank line after the game's version information, to make * it stand apart from the list of library and VM version numbers */ showVersion() { inherited(); "\b"; } ; /* ------------------------------------------------------------------------ */ /* * The main adv3Lite library ID. */ moduleAdv3Lite: ModuleID name = 'adv3Lite Library' byline = 'by Eric Eve' htmlByline = 'by <a href="mailto:eric.eve@hmc.ox.ac.uk">' + 'Eric Eve</a>' version = '2.1.1.18' /* * We use a listing order of 50 so that, if all of the other credits * use the defaults, we appear after the game's own credits * (conventionally at listing order 1) and before any extension * credits (which inherit the default order 100), but so that * there's room for extensions that want to appear before us, or * after us but before any default-ordered extensions. */ listingOrder = 50 ; /* ------------------------------------------------------------------------ */ /* * An ID module not for the library but for the T3 VM itself. This * doesn't display any credit information, but displays version number * information for the VM so that the "version" command shows what * version of the interpreter is in use. */ ModuleID showVersion() { local vsn = t3GetVMVsn(); /* * show the version information - note that we must decompose * the version number into the standard 3-part dotted string */ showVersionMsg('T3 VM (' + t3GetVMID() + ')', '' + (vsn >> 16) + '.' + ((vsn >> 8) & 0xFF) + '.' + (vsn & 0xFF)); "\n"; } /* * Use a very high listing order so that we're the last thing shown. */ listingOrder = 10000 ;
Adv3Lite Library Reference Manual
Generated on 26/02/2025 from adv3Lite version 2.2
Generated on 26/02/2025 from adv3Lite version 2.2