I6 Template Layer

Inform 7 6M62ContentsIntroductionFunction IndexRules Index

Definitions.i6t

Definitions contents

VM Target Constants.

Inform can compile story files for four different virtual machines (or VMs): Z-machine versions 5, 6 and 8, and Glulx.

When compiling to Glulx, the I6 compiler predefines the constant TARGET_GLULX and also sets WORDSIZE to 4; but when compiling to Z, we shouldn't assume it has this modern habit, so we simulate the same effect.

18#Ifndef WORDSIZE; ! compiling with Z-code only compiler 19Constant TARGET_ZCODE; 20Constant WORDSIZE 2; 21#Endif;

Wordsize-Dependent Definitions.

The old I6 library used to confuse Z-vs-G with 16-vs-32-bit, but we try to separate these distinctions here, even though at present the Z-machine is our only 16-bit target and Glulx our only 32-bit one. The WORDSIZE constant is the word size in bytes, so is the multiplier between -> and --> offsets in I6 pointer syntax.

(1) NULL is used, as in C, to represent a null value or pointer. In C, this is conventionally 0, but here it is the maximum unsigned value which can be stored, pointing to the topmost byte in the directly addressable memory map; this means it is also -1 when regarded as a signed twos-complement integer, but we write it as an unsigned hexadecimal address for clarity's sake.

(2) WORD_HIGHBIT is the most significant bit in the VM's data word.

(3) IMPROBABLE_VALUE is one which is unlikely but still possible to be a genuine I7 value. The efficiency of some algorithms depends on how well chosen this is: they would ran badly if we chose 1, for instance.

(4) MAX_POSITIVE_NUMBER is the largest representable positive (signed) integer, in twos-complement form.

(5) REPARSE_CODE is a magic value used in the I6 library's parser to signal that some code which ought to have been parsing a command has in fact rewritten it, so that the whole command must be re-parsed afresh. (Returning this value is like throwing an exception in a language like Java, though we don't implement it that way.) A comment in the 6/11 library reads: "The parser rather gunkily adds addresses to REPARSE_CODE for some purposes. And expects the result to be greater than REPARSE_CODE (signed comparison). So Glulx Inform is limited to a single gigabyte of storage, for the moment." Guilty as charged, but the gigabyte story file is a remote prospect for now: even megabyte story files are off the horizon. Anyway, it's this comparison issue which means we need a different value for each possible word size.

60#Iftrue (WORDSIZE == 2); 61Constant NULL = $ffff; 62Constant WORD_HIGHBIT = $8000; 63Constant WORD_NEXTTOHIGHBIT = $4000; 64Constant IMPROBABLE_VALUE = $7fe3; 65Constant MAX_POSITIVE_NUMBER 32767; 66Constant MIN_NEGATIVE_NUMBER -32768; 67Constant REPARSE_CODE = 10000; 68#Endif; 69 70#Iftrue (WORDSIZE == 4); 71Constant NULL = $ffffffff; 72Constant WORD_HIGHBIT = $80000000; 73Constant WORD_NEXTTOHIGHBIT = $40000000; 74Constant IMPROBABLE_VALUE = $deadce11; 75Constant MAX_POSITIVE_NUMBER 2147483647; 76Constant MIN_NEGATIVE_NUMBER -2147483648; 77Constant REPARSE_CODE = $40000000; 78#Endif;

Z-Machine Definitions.

The Z-machine contains certain special constants and variables at fixed position in its "header"; the addresses of these are given below. See The Z-Machine Standards Document, version 1.0, for details.

INDIV_PROP_START is the lowest number of any "individual property", an I6 internal quantity defined by the compiler when the target is Glulx but not for Z.

90#Ifdef TARGET_ZCODE; 91 92Global max_z_object; 93 94Constant INDIV_PROP_START 64; 95 96! Offsets into Z-machine header: 97 98Constant HDR_ZCODEVERSION = $00; ! byte 99Constant HDR_TERPFLAGS = $01; ! byte 100Constant HDR_GAMERELEASE = $02; ! word 101Constant HDR_HIGHMEMORY = $04; ! word 102Constant HDR_INITIALPC = $06; ! word 103Constant HDR_DICTIONARY = $08; ! word 104Constant HDR_OBJECTS = $0A; ! word 105Constant HDR_GLOBALS = $0C; ! word 106Constant HDR_STATICMEMORY = $0E; ! word 107Constant HDR_GAMEFLAGS = $10; ! word 108Constant HDR_GAMESERIAL = $12; ! six ASCII characters 109Constant HDR_ABBREVIATIONS = $18; ! word 110Constant HDR_FILELENGTH = $1A; ! word 111Constant HDR_CHECKSUM = $1C; ! word 112Constant HDR_TERPNUMBER = $1E; ! byte 113Constant HDR_TERPVERSION = $1F; ! byte 114Constant HDR_SCREENHLINES = $20; ! byte 115Constant HDR_SCREENWCHARS = $21; ! byte 116Constant HDR_SCREENWUNITS = $22; ! word 117Constant HDR_SCREENHUNITS = $24; ! word 118Constant HDR_FONTWUNITS = $26; ! byte 119Constant HDR_FONTHUNITS = $27; ! byte 120Constant HDR_ROUTINEOFFSET = $28; ! word 121Constant HDR_STRINGOFFSET = $2A; ! word 122Constant HDR_BGCOLOUR = $2C; ! byte 123Constant HDR_FGCOLOUR = $2D; ! byte 124Constant HDR_TERMCHARS = $2E; ! word 125Constant HDR_PIXELSTO3 = $30; ! word 126Constant HDR_TERPSTANDARD = $32; ! two bytes 127Constant HDR_ALPHABET = $34; ! word 128Constant HDR_EXTENSION = $36; ! word 129Constant HDR_UNUSED = $38; ! two words 130Constant HDR_INFORMVERSION = $3C; ! four ASCII characters 131 132#Endif;

Glulx Definitions.

We make similar header definitions for Glulx. Extensive further definitions, of constants needed to handle the Glk I/O layer, can be found in the "Infglk" section of Glulx.i6t; they are not used in the rest of the template layer, and would only get in the way here.

141#IFDEF TARGET_GLULX; 142 143Global unicode_gestalt_ok; ! Set if interpreter supports Unicode 144 145! Offsets into Glulx header and start of ROM: 146 147Constant HDR_MAGICNUMBER = $00; ! long word 148Constant HDR_GLULXVERSION = $04; ! long word 149Constant HDR_RAMSTART = $08; ! long word 150Constant HDR_EXTSTART = $0C; ! long word 151Constant HDR_ENDMEM = $10; ! long word 152Constant HDR_STACKSIZE = $14; ! long word 153Constant HDR_STARTFUNC = $18; ! long word 154Constant HDR_DECODINGTBL = $1C; ! long word 155Constant HDR_CHECKSUM = $20; ! long word 156Constant ROM_INFO = $24; ! four ASCII characters 157Constant ROM_MEMORYLAYOUT = $28; ! long word 158Constant ROM_INFORMVERSION = $2C; ! four ASCII characters 159Constant ROM_COMPVERSION = $30; ! four ASCII characters 160Constant ROM_GAMERELEASE = $34; ! short word 161Constant ROM_GAMESERIAL = $36; ! six ASCII characters 162 163#Endif;

Powers of Two.

I6 lacks support for logical shifts, and the Z-machine opcodes which bear on this are not always well supported, so the I6 library has traditionally used a lookup table for the values of 215-n where 0 ≤ n ≤ 11.

171Array PowersOfTwo_TB 172  --> $$100000000000 173      $$010000000000 174      $$001000000000 175      $$000100000000 176      $$000010000000 177      $$000001000000 178      $$000000100000 179      $$000000010000 180      $$000000001000 181      $$000000000100 182      $$000000000010 183      $$000000000001; 184 185Array IncreasingPowersOfTwo_TB 186  --> $$0000000000000001 187      $$0000000000000010 188      $$0000000000000100 189      $$0000000000001000 190      $$0000000000010000 191      $$0000000000100000 192      $$0000000001000000 193      $$0000000010000000 194      $$0000000100000000 195      $$0000001000000000 196      $$0000010000000000 197      $$0000100000000000 198      $$0001000000000000 199      $$0010000000000000 200      $$0100000000000000 201      $$1000000000000000;

Text Styles.

These are the styles of text distinguished by the template layer, though they are not required to look different from each other on any given VM. The codes are independent of the VM targetted, though in fact they are equal to Glulx style numbers as conventionally used. (The Z-machine renders some as roman, some as bold, but for instance makes HEADER_VMSTY and SUBHEADER_VMSTY indistinguishable to the eye.) Glulx's system of styles is one of its weakest points from an IF author's perspective, since it is all but impossible to achieve the text effects one might want – boldface, for instance, or red text – and text rendering is almost the only area in which it is clearly inferior to the Z-machine, which it was designed to replace. Still, using these styles when we can will get the most out of it, and for unornamental works Glulx is fine in practice.

218Constant NORMAL_VMSTY = 0; 219Constant HEADER_VMSTY = 3; 220Constant SUBHEADER_VMSTY = 4; 221Constant ALERT_VMSTY = 5; 222Constant NOTE_VMSTY = 6; 223Constant BLOCKQUOTE_VMSTY = 7; 224Constant INPUT_VMSTY = 8;

Colour Numbers.

These are traditional colour names: quite who it was who thought that azure was the same colour as cyan is now unclear. Colour is, again, not easy to arrange on Glulx, but there is some workaround code.

232Constant CLR_DEFAULT = 1; 233Constant CLR_BLACK = 2; 234Constant CLR_RED = 3; 235Constant CLR_GREEN = 4; 236Constant CLR_YELLOW = 5; 237Constant CLR_BLUE = 6; 238Constant CLR_MAGENTA = 7; Constant CLR_PURPLE = 7; 239Constant CLR_CYAN = 8; Constant CLR_AZURE = 8; 240Constant CLR_WHITE = 9;

Window Numbers.

Although Glulx can support elaborate tessalations of windows on screen (if the complexity of handling this can be mastered), the Z-machine has much more limited resources in general, so the template layer assumes a simple screen model: there are just two screen areas, the scrolling main window in which commands are typed and responses printed, and the fixed status line bar at the top of the screen.

251Constant WIN_ALL = 0; ! Both windows at once 252Constant WIN_STATUS = 1; 253Constant WIN_MAIN = 2;

Paragraphing Flags.

I am not sure many dictionaries would countenance "to paragraph" as a verb, but never mind: the reference here is to the algorithm used to place paragraph breaks within text, which uses bitmaps composed of the following.

261Constant PARA_COMPLETED = 1; 262Constant PARA_PROMPTSKIP = 2; 263Constant PARA_SUPPRESSPROMPTSKIP = 4; 264Constant PARA_NORULEBOOKBREAKS = 8; 265Constant PARA_CONTENTEXPECTED = 16;

Descriptors in the Language of Play.

The following constants, which must be different in value from the number of any I6 attribute, are used in the LanguageDescriptors table found in the definition of the language of play.

273Constant POSSESS_PK = $100; 274Constant DEFART_PK = $101; 275Constant INDEFART_PK = $102;

Run-Time Problem Numbers.

The enumeration sequence here must correspond to that in the file of RTP texts, which is used to generate the HTML pages displayed by the Inform user interface when a run-time problem has occurred. (For instance, the file of RTP texts includes the heading "P17 - Can't divide by zero", equivalent to RTP_DIVZERO being 17 below.) There is no significance to the sequence, which is simply the historical order in which they were added to I7.

287Constant RTP_BACKDROP = 1; 288Constant RTP_EXITDOOR = 2; 289Constant RTP_NOEXIT = 3; 290Constant RTP_CANTCHANGE = 4; 291Constant RTP_IMPREL = 5; 292Constant RTP_RULESTACK = 6; ! Now out of use 293Constant RTP_TOOMANYRULEBOOKS = 7; 294Constant RTP_TOOMANYEVENTS = 8; 295Constant RTP_BADPROPERTY = 9; 296Constant RTP_UNPROVIDED = 10; 297Constant RTP_UNSET = 11; 298Constant RTP_TOOMANYACTS = 12; 299Constant RTP_CANTABANDON = 13; 300Constant RTP_CANTEND = 14; 301Constant RTP_CANTMOVENOTHING = 15; 302Constant RTP_CANTREMOVENOTHING = 16; 303Constant RTP_DIVZERO = 17; 304Constant RTP_BADVALUEPROPERTY = 18; 305Constant RTP_NOTBACKDROP = 19; 306Constant RTP_TABLE_NOCOL = 20; 307Constant RTP_TABLE_NOCORR = 21; 308Constant RTP_TABLE_NOROW = 22; 309Constant RTP_TABLE_NOENTRY = 23; 310Constant RTP_TABLE_NOTABLE = 24; 311Constant RTP_TABLE_NOMOREBLANKS = 25; 312Constant RTP_TABLE_NOROWS = 26; 313Constant RTP_TABLE_CANTSORT = 27; 314Constant RTP_NOTINAROOM = 28; 315Constant RTP_BADTOPIC = 29; 316Constant RTP_ROUTELESS = 30; 317Constant RTP_PROPOFNOTHING = 31; 318Constant RTP_DECIDEONWRONGKIND = 32; 319Constant RTP_DECIDEONNOTHING = 33; 320Constant RTP_TABLE_CANTSAVE = 34; 321Constant RTP_TABLE_WONTFIT = 35; 322Constant RTP_TABLE_BADFILE = 36; 323Constant RTP_LOWLEVELERROR = 37; 324Constant RTP_DONTIGNORETURNSEQUENCE = 38; 325Constant RTP_SAYINVALIDSNIPPET = 39; 326Constant RTP_SPLICEINVALIDSNIPPET = 40; 327Constant RTP_INCLUDEINVALIDSNIPPET = 41; 328Constant RTP_LISTWRITERMEMORY = 42; 329Constant RTP_CANTREMOVEPLAYER = 43; 330Constant RTP_CANTREMOVEDOORS = 44; 331Constant RTP_CANTCHANGEOFFSTAGE = 45; 332Constant RTP_MSTACKMEMORY = 46; 333Constant RTP_TYPECHECK = 47; 334Constant RTP_FILEIOERROR = 48; 335Constant RTP_HEAPERROR = 49; 336Constant RTP_LISTRANGEERROR = 50; 337Constant RTP_REGEXPSYNTAXERROR = 51; 338Constant RTP_NOGLULXUNICODE = 52; 339Constant RTP_BACKDROPONLY = 53; 340Constant RTP_NOTTHING = 54; 341Constant RTP_SCENEHASNTSTARTED = 55; 342Constant RTP_SCENEHASNTENDED = 56; 343Constant RTP_NEGATIVEROOT = 57; 344Constant RTP_TABLE_CANTRUNTHROUGH = 58; 345Constant RTP_CANTITERATE = 59; 346Constant RTP_WRONGASSIGNEDKIND = 60; 347Constant RTP_CANTBEOFFSTAGE = 61; 348Constant RTP_RELKINDVIOLATION = 62; 349Constant RTP_CANTMAKEPART = 63; 350Constant RTP_TEXTTOKENTOOHARD = 64; 351Constant RTP_TABLE_NOTABLE2 = 65; 352Constant RTP_RELATIONCHANGEIMPOSSIBLE = 66; 353Constant RTP_RELMINIMAL = 67; 354Constant RTP_LISTSIZENEGATIVE = 68; 355Constant RTP_REGIONSNOTADJACENT = 69; 356

Template Activities.

These are the activities defined in the Standard Rules. Most, though not all, are carried out by explicit function calls in the template layer, which is why we need their ID numbers: note that NI assigns each activity a unique ID number on creation, counting upwards from 0, and that it processes the Standard Rules before any other source text. (These numbers must correspond both to those in the source of NI, and to the creation sequence in the Standard Rules.)

368Constant PRINTING_THE_NAME_ACT = 0; 369Constant PRINTING_THE_PLURAL_NAME_ACT = 1; 370Constant PRINTING_A_NUMBER_OF_ACT = 2; 371Constant PRINTING_ROOM_DESC_DETAILS_ACT = 3; 372Constant PRINTING_INVENTORY_DETAILS_ACT = 4; 373Constant LISTING_CONTENTS_ACT = 5; 374Constant GROUPING_TOGETHER_ACT = 6; 375Constant WRITING_A_PARAGRAPH_ABOUT_ACT = 7; 376Constant LISTING_NONDESCRIPT_ITEMS_ACT = 8; 377 378Constant PRINTING_NAME_OF_DARK_ROOM_ACT = 9; 379Constant PRINTING_DESC_OF_DARK_ROOM_ACT = 10; 380Constant PRINTING_NEWS_OF_DARKNESS_ACT = 11; 381Constant PRINTING_NEWS_OF_LIGHT_ACT = 12; 382Constant REFUSAL_TO_ACT_IN_DARK_ACT = 13; 383 384Constant CONSTRUCTING_STATUS_LINE_ACT = 14; 385Constant PRINTING_BANNER_TEXT_ACT = 15; 386 387Constant READING_A_COMMAND_ACT = 16; 388Constant DECIDING_SCOPE_ACT = 17; 389Constant DECIDING_CONCEALED_POSSESS_ACT = 18; 390Constant DECIDING_WHETHER_ALL_INC_ACT = 19; 391Constant CLARIFYING_PARSERS_CHOICE_ACT = 20; 392Constant ASKING_WHICH_DO_YOU_MEAN_ACT = 21; 393Constant PRINTING_A_PARSER_ERROR_ACT = 22; 394Constant SUPPLYING_A_MISSING_NOUN_ACT = 23; 395Constant SUPPLYING_A_MISSING_SECOND_ACT = 24; 396Constant IMPLICITLY_TAKING_ACT = 25; 397Constant STARTING_VIRTUAL_MACHINE_ACT = 26; 398 399Constant AMUSING_A_VICTORIOUS_PLAYER_ACT = 27; 400Constant PRINTING_PLAYERS_OBITUARY_ACT = 28; 401Constant DEALING_WITH_FINAL_QUESTION_ACT = 29; 402 403Constant PRINTING_LOCALE_DESCRIPTION_ACT = 30; 404Constant CHOOSING_NOTABLE_LOCALE_OBJ_ACT = 31; 405Constant PRINTING_LOCALE_PARAGRAPH_ACT = 32; 406 407Constant PRINTING_RESPONSE_ACT = 33;

Template Rulebooks.

Rulebooks are created in a similar way, and again are numbered upwards from 0 in order of creation. These are the ones used in the template layer. (These numbers must correspond both to those in the source of NI, and to the creation sequence in the Standard Rules.)

416Constant STARTUP_RB = 0; 417Constant TURN_SEQUENCE_RB = 1; 418Constant SHUTDOWN_RB = 2; 419 420Constant WHEN_PLAY_BEGINS_RB = 4; 421Constant WHEN_PLAY_ENDS_RB = 5; 422Constant WHEN_SCENE_BEGINS_RB = 6; 423Constant WHEN_SCENE_ENDS_RB = 7; 424 425Constant ACTION_PROCESSING_RB = 9; 426Constant SETTING_ACTION_VARIABLES_RB = 10; 427Constant SPECIFIC_ACTION_PROCESSING_RB = 11; 428 429Constant ACCESSIBILITY_RB = 13; 430Constant REACHING_INSIDE_RB = 14; 431Constant REACHING_OUTSIDE_RB = 15; 432Constant VISIBLE_RB = 16; 433 434Constant PERSUADE_RB = 17; 435Constant UNSUCCESSFUL_ATTEMPT_RB = 18; 436 437Constant AFTER_RB = 23; 438Constant REPORT_RB = 24; 439 440Constant MULTIPLE_ACTION_PROCESSING_RB = 26;

Kind IDs.

These are filled in automatically by NI, and have the same names as are used in the NI source (and in the Load-.i6t sections): for instance NUMBER_TY.

447{-call:Kinds::Constructors::compile_I6_constants}

Parser Error Numbers.

The traditional ways in which the I6 library's parser, which we adopt here more or less intact, can give up on a player's command. See the Inform Designer's Manual, 4th edition, for details.

455Constant STUCK_PE = 1; 456Constant UPTO_PE = 2; 457Constant NUMBER_PE = 3; 458Constant ANIMA_PE = 4; 459Constant CANTSEE_PE = 5; 460Constant TOOLIT_PE = 6; 461Constant NOTHELD_PE = 7; 462Constant MULTI_PE = 8; 463Constant MMULTI_PE = 9; 464Constant VAGUE_PE = 10; 465Constant EXCEPT_PE = 11; 466Constant VERB_PE = 12; 467Constant SCENERY_PE = 13; 468Constant ITGONE_PE = 14; 469Constant JUNKAFTER_PE = 15; 470Constant TOOFEW_PE = 16; 471Constant NOTHING_PE = 17; 472Constant ASKSCOPE_PE = 18; 473Constant NOTINCONTEXT_PE = 19; 474Constant BLANKLINE_PE = 20; ! Not formally a parser error, but used by I7 as if 475Constant ANIMAAGAIN_PE = 21; 476Constant COMMABEGIN_PE = 22; 477Constant MISSINGPERSON_PE = 23; 478Constant ANIMALISTEN_PE = 24; 479Constant TOTALK_PE = 25;

Scope Searching Reasons.

The parser makes use of a mechanism for searching through the objects currently "in scope", which basically means visible to the actor who would perform the action envisaged by the command being parsed. It is sometimes useful to behave differently depending on why this scope searching is being done, so the following constants enumerate the possibilities.

I6's EACH_TURN_REASON, REACT_BEFORE_REASON and REACT_AFTER_REASON have been removed from this list as no longer meaningful; hence the lacuna in numbering.

493Constant PARSING_REASON = 0; 494Constant TALKING_REASON = 1; 495Constant EACH_TURN_REASON = 2; 496Constant LOOPOVERSCOPE_REASON = 5; 497Constant TESTSCOPE_REASON = 6;

Token Types.

Tokens are the indecomposable pieces of a grammar line making up a possible reading of a command; some are literal words, others stand for "any named object in scope", and so on. The following codes identify the possibilities. The *_TOKEN constants must not be altered without modifying the I6 compiler to match (so, basically, they must not be altered at all).

507Constant ILLEGAL_TT = 0; ! Types of grammar token: illegal 508Constant ELEMENTARY_TT = 1; ! (one of those below) 509Constant PREPOSITION_TT = 2; ! e.g. 'into' 510Constant ROUTINE_FILTER_TT = 3; ! e.g. noun=CagedCreature 511Constant ATTR_FILTER_TT = 4; ! e.g. edible 512Constant SCOPE_TT = 5; ! e.g. scope=Spells 513Constant GPR_TT = 6; ! a general parsing routine 514 515Constant NOUN_TOKEN = 0; ! The elementary grammar tokens, and 516Constant HELD_TOKEN = 1; ! the numbers compiled by I6 to 517Constant MULTI_TOKEN = 2; ! encode them 518Constant MULTIHELD_TOKEN = 3; 519Constant MULTIEXCEPT_TOKEN = 4; 520Constant MULTIINSIDE_TOKEN = 5; 521Constant CREATURE_TOKEN = 6; 522Constant SPECIAL_TOKEN = 7; 523Constant NUMBER_TOKEN = 8; 524Constant TOPIC_TOKEN = 9; 525Constant ENDIT_TOKEN = 15; ! Value used to mean "end of grammar line"

GPR Return Values.

GRP stands for "General Parsing Routine", an I6 routine which acts as a grammar token: again, see the Inform Designer's Manual, 4th edition, for details.

In Library 6/11, GPR_NOUN is defined as $ff00, but this would fail on Glulx: it needs to be $ffffff00 on 32-bit virtual machines. It appears that GPR_NOUN to GPR_CREATURE, though documented in the old Inform Translator's Manual, were omitted when this was consolidated into the DM4, so that they effectively disappeared from view. But they might still be useful for implementing inflected forms of nouns, so we have retained them here regardless.

541Constant GPR_FAIL = -1; ! Return values from General Parsing 542Constant GPR_PREPOSITION = 0; ! Routines 543Constant GPR_NUMBER = 1; 544Constant GPR_MULTIPLE = 2; 545Constant GPR_REPARSE = REPARSE_CODE; 546Constant GPR_NOUN = -256; ! Reparse, but as |NOUN_TOKEN| this time 547Constant GPR_HELD = GPR_NOUN + 1; ! And so on 548Constant GPR_MULTI = GPR_NOUN + 2; 549Constant GPR_MULTIHELD = GPR_NOUN + 3; 550Constant GPR_MULTIEXCEPT = GPR_NOUN + 4; 551Constant GPR_MULTIINSIDE = GPR_NOUN + 5; 552Constant GPR_CREATURE = GPR_NOUN + 6;

List Styles.

These constants make up bitmaps of the options in use when listing objects.

558Constant NEWLINE_BIT = $$0000000000000001; ! New-line after each entry 559Constant INDENT_BIT = $$0000000000000010; ! Indent each entry by depth 560Constant FULLINV_BIT = $$0000000000000100; ! Full inventory information after entry 561Constant ENGLISH_BIT = $$0000000000001000; ! English sentence style, with commas and and 562Constant RECURSE_BIT = $$0000000000010000; ! Recurse downwards with usual rules 563Constant ALWAYS_BIT = $$0000000000100000; ! Always recurse downwards 564Constant TERSE_BIT = $$0000000001000000; ! More terse English style 565Constant PARTINV_BIT = $$0000000010000000; ! Only brief inventory information after entry 566Constant DEFART_BIT = $$0000000100000000; ! Use the definite article in list 567Constant WORKFLAG_BIT = $$0000001000000000; ! At top level (only), only list objects 568                                                  ! which have the "workflag" attribute 569Constant ISARE_BIT = $$0000010000000000; ! Print " is" or " are" before list 570Constant CONCEAL_BIT = $$0000100000000000; ! Omit objects with "concealed" or "scenery": 571                                                  ! if WORKFLAG_BIT also set, then does not 572                                                  ! apply at top level, but does lower down 573Constant NOARTICLE_BIT = $$0001000000000000; ! Print no articles, definite or not 574Constant EXTRAINDENT_BIT = $$0010000000000000; ! New in I7: extra indentation of 1 level 575Constant CFIRSTART_BIT = $$0100000000000000; ! Capitalise first article in list

Lengths Of Time.

Inform measures time in minutes.

581Constant QUARTER_HOUR = 15; 582Constant HALF_HOUR = 30; 583Constant ONE_HOUR = 60; 584Constant TWELVE_HOURS = 720; 585Constant TWENTY_FOUR_HOURS = 1440;

Empty Text.

The I6 compiler does not optimise string compilation: if it needs to compile the (packed, read-only) string "exemplum" twice, it will compile two copies. This is slightly wasteful on memory, though in practice the loss is not enough for us to care. But we do want to avoid this in I7 because, to make string-sorting algorithms more efficient, we want direct numerical comparison of packed addresses to be equivalent to string comparison: and that means the text "exemplum" has to be compiled once and once only. There's a general mechanism for this in NI, but the single case most often needed is the empty text, since this is the default value for text variables and properties: we give it a name as follows.

600Constant EMPTY_TEXT_PACKED ""; 601Array EMPTY_TEXT_VALUE --> CONSTANT_PACKED_TEXT_STORAGE EMPTY_TEXT_PACKED;

Empty Table.

Similarly: the default value for the "table" kind of value, a Table containing no rows and no columns.

608Array TheEmptyTable --> 0 0;

Empty Set.

The falsity proposition describes the empty set of objects, and is the zero value for the "description" kind of value.

615[ Prop_Falsity reason obj; return 0; ];

Score and Rankings Table.

The following command tells NI to compile constant definitions for MAX_SCORE and/or RANKING_TABLE, in cases where there are scores and rankings. If there's no score, we define MAX_SCORE as 0 anyway; if there's no ranking table, RANKING_TABLE is left undefined, so that we can #ifdef this possibility later.

625{-call:Tables::Support::compile_max_score} 626#Ifndef MAX_SCORE; 627Global MAX_SCORE = 0; 628#Endif;

Template Attributes.

An I6 attribute is equivalent to an I7 "either/or property", though the latter are not always translated into I6 attributes because the Z-machine has only a limited number of attributes to use. Here, we define attributes used by the template.

Many concepts in I6 correspond directly to their successors in I7, even if details may vary. (Value properties are a case in point.) Attributes are the opposite of this: indeed, no I6 concept is more fragmented in its I7 equivalents. All but one of the old I6 library attributes are still used (the general attribute, for miscellaneous use, has been removed: it more often invited abuse than use); and a few new attributes have been added. But they are used for a variety of purposes. Some do correspond exactly to either/or properties in I7, but others are a sort of signature for I7 kinds. (So that for I7 use they are read-only.) Others still are used by the template layer as part of the implementation of services for I7, but are not visible to I7 source text as storage.

649Attribute absent; ! Used to mark objects removed from play 650Attribute animate; ! I6-level marker for I7 kind "person" 651Attribute clothing; ! = I7 "wearable" 652Attribute concealed; ! = I7 "undescribed" 653Attribute container; ! I6-level marker for I7 kind "container" 654Attribute door; ! I6-level marker for I7 kind "door" 655Attribute edible; ! = I7 "edible" vs "inedible" 656Attribute enterable; ! = I7 "enterable" 657Attribute light; ! = I7 "lighted" vs "dark" 658Attribute lockable; ! = I7 "lockable" 659Attribute locked; ! = I7 "locked" 660Attribute moved; ! = I7 "handled" 661Attribute on; ! = I7 "switched on" vs "switched off" 662Attribute open; ! = I7 "open" vs "closed" 663Attribute openable; ! = I7 "openable" 664Attribute scenery; ! = I7 "scenery" 665Attribute static; ! = I7 "fixed in place" vs "portable" 666Attribute supporter; ! I6-level marker for I7 kind "supporter" 667Attribute switchable; ! I6-level marker for I7 kind "device" 668Attribute talkable; ! Not currently used by I7, but retained for possible future use 669Attribute transparent; ! = I7 "transparent" vs "opaque" 670Attribute visited; ! = I7 "visited" 671Attribute worn; ! marks that an object tree edge represents wearing 672 673Attribute male; ! not directly used by I7, but available for languages with genders 674Attribute female; ! = I7 "female" vs "male" 675Attribute neuter; ! = I7 "neuter" 676Attribute pluralname; ! = I7 "plural-named" 677Attribute ambigpluralname; ! = I7 "ambiguously plural" 678Attribute proper; ! = I7 "proper-named" 679Attribute remove_proper; ! remember to remove proper again when using ChangePlayer next 680 681Attribute privately_named; ! New in I7 682Attribute mentioned; ! New in I7 683Attribute pushable; ! New in I7 684 685Attribute mark_as_room; ! Used in I7 to speed up testing "ofclass K1_room" 686Attribute mark_as_thing; ! Used in I7 to speed up testing "ofclass K2_thing" 687 688Attribute workflag; ! = I7 "marked for listing", but basically temporary workspace 689Attribute workflag2; ! new in I7 and also temporary workspace 690Constant list_filter_permits = privately_named; ! another I7 listwriter convenience

Template Properties.

As remarked above, these more often correspond to value properties in I7. To an experienced I6 user, though, the death toll of abolished I6 properties in I7 is breathtaking: in alphabetical order, after, cant_go, daemon, each_turn, invent, life, number, orders, react_after, react_before, time_left, time_out, when_closed, when_off, when_on, when_open. In May 2008, the direction properties n_to, s_to, e_to, ..., out_to joined the list of the missing.

The losses are numerous because of the shift from I6's object orientation to I7's rule orientation: information about the behaviour of objects is no longer thought of as data attached to them. At that, it could have been worse: a few unused I6 library properties have been retained for possible future use.

708Property add_to_scope; ! used as in I6 to place component parts in scope 709Property article "a"; ! used as in I6 to implement articles 710Property capacity 100; ! = I7 "carrying capacity" 711Property component_child; ! new in I7: forest structure holding "part of" relation 712Property component_parent; ! new in I7 713Property component_sibling; ! new in I7 714Property description; ! = I7 "description" 715Property door_dir; ! used to implement two-sided doors, but holds direction object, not a property 716Property door_to; ! used as in I6 to implement two-sided doors 717Property found_in; ! used as in I6 to implement two-sided doors and backdrops 718Property initial; ! = I7 "initial description" 719Property list_together; ! used as in I6 to implement "grouping together" activity 720Property map_region; ! new in I7 721Property parse_name 0; ! used as in I6 to implement "Understand... as..." grammars 722Property plural; ! used as in I6 to implement plural names for duplicate objects 723Property regional_found_in; ! new in I7 724Property room_index; ! new in I7: storage for route-finding 725Property short_name 0; ! = I7 "printed name" 726Property vector; ! new in I7: storage for route-finding 727Property with_key; ! = I7 "matching key" 728 729Property KD_Count; ! Instance count of the kind of the current object 730Property IK1_Count; ! These are instance counts within kinds K1, K2, ... 731Property IK2_Count; ! and it is efficient to declare the common ones with Property 732Property IK4_Count; ! since this results in a slightly smaller story file 733Property IK5_Count; 734Property IK6_Count; 735Property IK8_Count; 736 737Property IK1_link; ! These are for linked lists used to make searches faster 738Property IK2_link; ! and again it's memory-efficient to declare the common ones 739Property IK5_link; ! 740Property IK6_link; ! 741Property IK8_link; ! 742 743Property articles; ! not used by I7, but an interesting hook in the parser 744Property grammar; ! not used by I7, but an interesting hook in the parser 745Property inside_description; ! not used by I7, but an interesting hook in the locale code 746Property short_name_indef 0; ! not used by I7, but an interesting hook in the listmaker

Loss of Life.

The loss of life is so appalling that I6 will not even compile a story file which doesn't define the property number life (well, strictly speaking, it checks the presence of constants suggesting the I6 library first, but the template layer does define constants like that). We define it as a null constant to be sure of avoiding any valid property number; I6 being typeless, that enables the veneer to compile again. (The relevant code is in CA__Pr, defined in the veneer.c section of I6.)

758Constant life = NULL;

Action Count.

The number of valid I7 actions in existence.

764Constant ActionCount = {-value:NUMBER_CREATED(action_name)};

Fake Actions.

Though sometimes useful for I6 coding tricks, fake actions – action numbers not corresponding to any action, but different from those of valid actions, and useable with a number of action syntaxes – are not conceptually present in I7 source text. They can only really exist at the I6 level because I6 is typeless; in I7 terms, there is no convenient kind of value which could represent both actions and fake actions while protecting each from confusion with the other.

See the Inform Designer's Manual, 4th edition, for what these are used for.

The following fake actions from the I6 library have been dropped here: ##LetGo, ##Receive, ##ThrownAt, ##Prompt, ##Places, ##Objects, ##Order, ##NotUnderstood.

783Fake_Action ListMiscellany; 784Fake_Action Miscellany; 785Fake_Action PluralFound; 786Fake_Action TheSame;

Formal Parameters.

These are needed for efficient run-time ambiguity resolution.

792Global formal_rv; 793Global formal_par0; 794Global formal_par1; 795Global formal_par2; 796Global formal_par3; 797Global formal_par4; 798Global formal_par5; 799Global formal_par6; 800Global formal_par7; 801Global unicode_temp;