B/defnt: Definitions Template.
 
@Purpose: Miscellaneous constant definitions, usually providing symbolic names
for otherwise inscrutable numbers, which are used throughout the template
layer.
 
@-------------------------------------------------------------------------------

@p 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.

@c
#Ifndef WORDSIZE; ! compiling with Z-code only compiler
Constant TARGET_ZCODE;
Constant WORDSIZE 2;
#Endif;

@p 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 {\it 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.

@c
#Iftrue (WORDSIZE == 2);
Constant NULL = $ffff;
Constant WORD_HIGHBIT = $8000;
Constant WORD_NEXTTOHIGHBIT = $4000;
Constant IMPROBABLE_VALUE = $7fe3;
Constant MAX_POSITIVE_NUMBER 32767;
Constant MIN_NEGATIVE_NUMBER -32768;
Constant REPARSE_CODE = 10000;
#Endif;

#Iftrue (WORDSIZE == 4);
Constant NULL = $ffffffff;
Constant WORD_HIGHBIT = $80000000;
Constant WORD_NEXTTOHIGHBIT = $40000000;
Constant IMPROBABLE_VALUE = $deadce11;
Constant MAX_POSITIVE_NUMBER 2147483647;
Constant MIN_NEGATIVE_NUMBER -2147483648;
Constant REPARSE_CODE = $40000000;
#Endif;

@p 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
{\it 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.

@c
#Ifdef TARGET_ZCODE;

Global max_z_object;

Constant INDIV_PROP_START 64;

! Offsets into Z-machine header:

Constant HDR_ZCODEVERSION     = $00;     ! byte
Constant HDR_TERPFLAGS        = $01;     ! byte
Constant HDR_GAMERELEASE      = $02;     ! word
Constant HDR_HIGHMEMORY       = $04;     ! word
Constant HDR_INITIALPC        = $06;     ! word
Constant HDR_DICTIONARY       = $08;     ! word
Constant HDR_OBJECTS          = $0A;     ! word
Constant HDR_GLOBALS          = $0C;     ! word
Constant HDR_STATICMEMORY     = $0E;     ! word
Constant HDR_GAMEFLAGS        = $10;     ! word
Constant HDR_GAMESERIAL       = $12;     ! six ASCII characters
Constant HDR_ABBREVIATIONS    = $18;     ! word
Constant HDR_FILELENGTH       = $1A;     ! word
Constant HDR_CHECKSUM         = $1C;     ! word
Constant HDR_TERPNUMBER       = $1E;     ! byte
Constant HDR_TERPVERSION      = $1F;     ! byte
Constant HDR_SCREENHLINES     = $20;     ! byte
Constant HDR_SCREENWCHARS     = $21;     ! byte
Constant HDR_SCREENWUNITS     = $22;     ! word
Constant HDR_SCREENHUNITS     = $24;     ! word
Constant HDR_FONTWUNITS       = $26;     ! byte
Constant HDR_FONTHUNITS       = $27;     ! byte
Constant HDR_ROUTINEOFFSET    = $28;     ! word
Constant HDR_STRINGOFFSET     = $2A;     ! word
Constant HDR_BGCOLOUR         = $2C;     ! byte
Constant HDR_FGCOLOUR         = $2D;     ! byte
Constant HDR_TERMCHARS        = $2E;     ! word
Constant HDR_PIXELSTO3        = $30;     ! word
Constant HDR_TERPSTANDARD     = $32;     ! two bytes
Constant HDR_ALPHABET         = $34;     ! word
Constant HDR_EXTENSION        = $36;     ! word
Constant HDR_UNUSED           = $38;     ! two words
Constant HDR_INFORMVERSION    = $3C;     ! four ASCII characters

#Endif;

@p 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.

@c
#IFDEF TARGET_GLULX;

Global unicode_gestalt_ok; ! Set if interpreter supports Unicode

! Offsets into Glulx header and start of ROM:

Constant HDR_MAGICNUMBER      = $00;     ! long word
Constant HDR_GLULXVERSION     = $04;     ! long word
Constant HDR_RAMSTART         = $08;     ! long word
Constant HDR_EXTSTART         = $0C;     ! long word
Constant HDR_ENDMEM           = $10;     ! long word
Constant HDR_STACKSIZE        = $14;     ! long word
Constant HDR_STARTFUNC        = $18;     ! long word
Constant HDR_DECODINGTBL      = $1C;     ! long word
Constant HDR_CHECKSUM         = $20;     ! long word
Constant ROM_INFO             = $24;     ! four ASCII characters
Constant ROM_MEMORYLAYOUT     = $28;     ! long word
Constant ROM_INFORMVERSION    = $2C;     ! four ASCII characters
Constant ROM_COMPVERSION      = $30;     ! four ASCII characters
Constant ROM_GAMERELEASE      = $34;     ! short word
Constant ROM_GAMESERIAL       = $36;     ! six ASCII characters

#Endif;

@p 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 $2^{15-n}$ where $0\leq n \leq 11$.

@c
Array PowersOfTwo_TB
  --> $$100000000000
      $$010000000000
      $$001000000000
      $$000100000000
      $$000010000000
      $$000001000000
      $$000000100000
      $$000000010000
      $$000000001000
      $$000000000100
      $$000000000010
      $$000000000001;

Array IncreasingPowersOfTwo_TB
  --> $$0000000000000001
      $$0000000000000010
      $$0000000000000100
      $$0000000000001000
      $$0000000000010000
      $$0000000000100000
      $$0000000001000000
      $$0000000010000000
      $$0000000100000000
      $$0000001000000000
      $$0000010000000000
	  $$0000100000000000
	  $$0001000000000000
	  $$0010000000000000
	  $$0100000000000000
	  $$1000000000000000;

@p 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.

@c
Constant NORMAL_VMSTY     = 0;
Constant HEADER_VMSTY     = 3;
Constant SUBHEADER_VMSTY  = 4;
Constant ALERT_VMSTY      = 5;
Constant NOTE_VMSTY       = 6;
Constant BLOCKQUOTE_VMSTY = 7;
Constant INPUT_VMSTY      = 8;

@p 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.

@c
Constant CLR_DEFAULT = 1;
Constant CLR_BLACK   = 2;
Constant CLR_RED     = 3;
Constant CLR_GREEN   = 4;
Constant CLR_YELLOW  = 5;
Constant CLR_BLUE    = 6;
Constant CLR_MAGENTA = 7; Constant CLR_PURPLE  = 7;
Constant CLR_CYAN    = 8; Constant CLR_AZURE   = 8;
Constant CLR_WHITE   = 9;

@p 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.

@c
Constant WIN_ALL     = 0; ! Both windows at once
Constant WIN_STATUS  = 1;
Constant WIN_MAIN    = 2;

@p 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.

@c
Constant PARA_COMPLETED          = 1;
Constant PARA_PROMPTSKIP         = 2;
Constant PARA_SUPPRESSPROMPTSKIP = 4;
Constant PARA_NORULEBOOKBREAKS   = 8;
Constant PARA_CONTENTEXPECTED    = 16;

@p 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.

@c
Constant POSSESS_PK  = $100;
Constant DEFART_PK   = $101;
Constant INDEFART_PK = $102;

@p 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.

@c
Constant RTP_BACKDROP                = 1;
Constant RTP_EXITDOOR                = 2;
Constant RTP_NOEXIT                  = 3;
Constant RTP_CANTCHANGE              = 4;
Constant RTP_IMPREL                  = 5;
Constant RTP_RULESTACK               = 6;
Constant RTP_TOOMANYRULEBOOKS        = 7;
Constant RTP_TOOMANYEVENTS           = 8;
Constant RTP_BADPROPERTY             = 9;
Constant RTP_UNPROVIDED              = 10;
Constant RTP_UNSET                   = 11;
Constant RTP_TOOMANYACTS             = 12;
Constant RTP_CANTABANDON             = 13;
Constant RTP_CANTEND                 = 14;
Constant RTP_CANTMOVENOTHING         = 15;
Constant RTP_CANTREMOVENOTHING       = 16;
Constant RTP_DIVZERO                 = 17;
Constant RTP_BADVALUEPROPERTY        = 18;
Constant RTP_NOTBACKDROP             = 19;
Constant RTP_TABLE_NOCOL             = 20;
Constant RTP_TABLE_NOCORR            = 21;
Constant RTP_TABLE_NOROW             = 22;
Constant RTP_TABLE_NOENTRY           = 23;
Constant RTP_TABLE_NOTABLE           = 24;
Constant RTP_TABLE_NOMOREBLANKS      = 25;
Constant RTP_TABLE_NOROWS            = 26;
Constant RTP_TABLE_CANTSORT          = 27;
Constant RTP_NOTINAROOM              = 28;
Constant RTP_BADTOPIC                = 29;
Constant RTP_ROUTELESS               = 30;
Constant RTP_PROPOFNOTHING           = 31;
Constant RTP_DECIDEONWRONGKIND       = 32;
Constant RTP_DECIDEONNOTHING         = 33;
Constant RTP_TABLE_CANTSAVE          = 34;
Constant RTP_TABLE_WONTFIT           = 35;
Constant RTP_TABLE_BADFILE           = 36;
Constant RTP_LOWLEVELERROR           = 37;
Constant RTP_DONTIGNORETURNSEQUENCE  = 38;
Constant RTP_SAYINVALIDSNIPPET       = 39;
Constant RTP_SPLICEINVALIDSNIPPET    = 40;
Constant RTP_INCLUDEINVALIDSNIPPET   = 41;
Constant RTP_LISTWRITERMEMORY        = 42;
Constant RTP_CANTREMOVEPLAYER        = 43;
Constant RTP_CANTREMOVEDOORS         = 44;
Constant RTP_CANTCHANGEOFFSTAGE      = 45;
Constant RTP_MSTACKMEMORY            = 46;
Constant RTP_TYPECHECK               = 47;
Constant RTP_FILEIOERROR             = 48;
Constant RTP_HEAPERROR               = 49;
Constant RTP_LISTRANGEERROR          = 50;
Constant RTP_REGEXPSYNTAXERROR       = 51;
Constant RTP_NOGLULXUNICODE          = 52;
Constant RTP_BACKDROPONLY            = 53;
Constant RTP_NOTTHING                = 54;
Constant RTP_SCENEHASNTSTARTED       = 55;
Constant RTP_SCENEHASNTENDED         = 56;
Constant RTP_NEGATIVEROOT            = 57;
Constant RTP_TABLE_CANTRUNTHROUGH    = 58;
Constant RTP_CANTITERATE             = 59;
Constant RTP_WRONGASSIGNEDKIND       = 60;

@p 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 {\it both} to those in the source of NI, {\it and} to the
creation sequence in the Standard Rules.)

@c
Constant PRINTING_THE_NAME_ACT           = 0;
Constant PRINTING_THE_PLURAL_NAME_ACT    = 1;
Constant PRINTING_A_NUMBER_OF_ACT        = 2;
Constant PRINTING_ROOM_DESC_DETAILS_ACT  = 3;
Constant LISTING_CONTENTS_ACT            = 4;
Constant GROUPING_TOGETHER_ACT           = 5;
Constant WRITING_A_PARAGRAPH_ABOUT_ACT   = 6;
Constant LISTING_NONDESCRIPT_ITEMS_ACT   = 7;

Constant PRINTING_NAME_OF_DARK_ROOM_ACT  = 8;
Constant PRINTING_DESC_OF_DARK_ROOM_ACT  = 9;
Constant PRINTING_NEWS_OF_DARKNESS_ACT   = 10;
Constant PRINTING_NEWS_OF_LIGHT_ACT      = 11;
Constant REFUSAL_TO_ACT_IN_DARK_ACT      = 12;

Constant CONSTRUCTING_STATUS_LINE_ACT    = 13;
Constant PRINTING_BANNER_TEXT_ACT        = 14;

Constant READING_A_COMMAND_ACT           = 15;
Constant DECIDING_SCOPE_ACT              = 16;
Constant DECIDING_CONCEALED_POSSESS_ACT  = 17;
Constant DECIDING_WHETHER_ALL_INC_ACT    = 18;
Constant CLARIFYING_PARSERS_CHOICE_ACT   = 19;
Constant ASKING_WHICH_DO_YOU_MEAN_ACT    = 20;
Constant PRINTING_A_PARSER_ERROR_ACT     = 21;
Constant SUPPLYING_A_MISSING_NOUN_ACT    = 22;
Constant SUPPLYING_A_MISSING_SECOND_ACT  = 23;
Constant IMPLICITLY_TAKING_ACT           = 24;
Constant STARTING_VIRTUAL_MACHINE_ACT    = 25;

Constant AMUSING_A_VICTORIOUS_PLAYER_ACT = 26;
Constant PRINTING_PLAYERS_OBITUARY_ACT   = 27;
Constant DEALING_WITH_FINAL_QUESTION_ACT = 28;

Constant PRINTING_LOCALE_DESCRIPTION_ACT = 29;
Constant CHOOSING_NOTABLE_LOCALE_OBJ_ACT = 30;
Constant PRINTING_LOCALE_PARAGRAPH_ACT   = 31;

@p 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 {\it both} to those in the source of NI,
{\it and} to the creation sequence in the Standard Rules.)

@c
Constant PROCEDURAL_RB                   = 0;

Constant STARTUP_RB                      = 1;
Constant TURN_SEQUENCE_RB                = 2;
Constant SHUTDOWN_RB                     = 3;

Constant WHEN_PLAY_BEGINS_RB             = 5;
Constant WHEN_PLAY_ENDS_RB               = 6;
Constant WHEN_SCENE_BEGINS_RB            = 7;
Constant WHEN_SCENE_ENDS_RB              = 8;

Constant ACTION_PROCESSING_RB            = 10;
Constant SETTING_ACTION_VARIABLES_RB     = 11;
Constant SPECIFIC_ACTION_PROCESSING_RB   = 12;

Constant ACCESSIBILITY_RB                = 14;
Constant REACHING_INSIDE_RB              = 15;
Constant REACHING_OUTSIDE_RB             = 16;
Constant VISIBLE_RB                      = 17;

Constant PERSUADE_RB                     = 18;
Constant UNSUCCESSFUL_ATTEMPT_RB         = 19;

Constant AFTER_RB                        = 24;
Constant REPORT_RB                       = 25;

@p 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|.

@c
{-call:Kinds::Constructors::compile_I6_constants}

@p 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 {\it Inform
Designer's Manual}, 4th edition, for details.

@c
Constant STUCK_PE     = 1;
Constant UPTO_PE      = 2;
Constant NUMBER_PE    = 3;
Constant ANIMA_PE     = 4;
Constant CANTSEE_PE   = 5;
Constant TOOLIT_PE    = 6;
Constant NOTHELD_PE   = 7;
Constant MULTI_PE     = 8;
Constant MMULTI_PE    = 9;
Constant VAGUE_PE     = 10;
Constant EXCEPT_PE    = 11;
Constant VERB_PE      = 12;
Constant SCENERY_PE   = 13;
Constant ITGONE_PE    = 14;
Constant JUNKAFTER_PE = 15;
Constant TOOFEW_PE    = 16;
Constant NOTHING_PE   = 17;
Constant ASKSCOPE_PE  = 18;
Constant NOTINCONTEXT_PE = 19;
Constant BLANKLINE_PE = 20; ! Not formally a parser error, but used by I7 as if

@p 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.

@c
Constant PARSING_REASON       = 0;
Constant TALKING_REASON       = 1;
Constant EACH_TURN_REASON     = 2;
Constant LOOPOVERSCOPE_REASON = 5;
Constant TESTSCOPE_REASON     = 6;

@p 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).

@c
Constant ILLEGAL_TT         = 0;    ! Types of grammar token: illegal
Constant ELEMENTARY_TT      = 1;    !     (one of those below)
Constant PREPOSITION_TT     = 2;    !     e.g. 'into'
Constant ROUTINE_FILTER_TT  = 3;    !     e.g. noun=CagedCreature
Constant ATTR_FILTER_TT     = 4;    !     e.g. edible
Constant SCOPE_TT           = 5;    !     e.g. scope=Spells
Constant GPR_TT             = 6;    !     a general parsing routine

Constant NOUN_TOKEN         = 0;    ! The elementary grammar tokens, and
Constant HELD_TOKEN         = 1;    ! the numbers compiled by I6 to
Constant MULTI_TOKEN        = 2;    ! encode them
Constant MULTIHELD_TOKEN    = 3;
Constant MULTIEXCEPT_TOKEN  = 4;
Constant MULTIINSIDE_TOKEN  = 5;
Constant CREATURE_TOKEN     = 6;
Constant SPECIAL_TOKEN      = 7;
Constant NUMBER_TOKEN       = 8;
Constant TOPIC_TOKEN        = 9;
Constant ENDIT_TOKEN        = 15;   ! Value used to mean "end of grammar line"

@p GPR Return Values.
GRP stands for ``General Parsing Routine'', an I6 routine which acts as a
grammar token: again, see the {\it 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 {\it 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.

@c
Constant GPR_FAIL           = -1;   ! Return values from General Parsing
Constant GPR_PREPOSITION    = 0;    ! Routines
Constant GPR_NUMBER         = 1;
Constant GPR_MULTIPLE       = 2;
Constant GPR_REPARSE        = REPARSE_CODE;
Constant GPR_NOUN           = -256; ! Reparse, but as |NOUN_TOKEN| this time
Constant GPR_HELD           = GPR_NOUN + 1; ! And so on
Constant GPR_MULTI          = GPR_NOUN + 2;
Constant GPR_MULTIHELD      = GPR_NOUN + 3;
Constant GPR_MULTIEXCEPT    = GPR_NOUN + 4;
Constant GPR_MULTIINSIDE    = GPR_NOUN + 5;
Constant GPR_CREATURE       = GPR_NOUN + 6;

@p List Styles.
These constants make up bitmaps of the options in use when listing objects.

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

@p Lengths Of Time.
Inform measures time in minutes.

@c
Constant QUARTER_HOUR = 15;
Constant HALF_HOUR = 30;
Constant ONE_HOUR = 60;
Constant TWELVE_HOURS = 720;
Constant TWENTY_FOUR_HOURS = 1440;

@p 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.

(This works because I6 constant definition is not like C preprocessor macro
expansion: |EMPTY_TEXT_VALUE| is equated with the address resulting from
compiling |""|, rather than being replaced with the blank text to be
recompiled each time.)

@c
Constant EMPTY_TEXT_VALUE "";

@p Empty Table.
Similarly: the default value for the ``table'' kind of value, a Table
containing no rows and no columns.

@c
Array TheEmptyTable --> 0 0;

@p Empty Rulebook.
Similarly. An empty rulebook is one whose array has first word equal to
|NULL|: we define a sequence of four |$ff| bytes so that the first word
will be |NULL| on either 16-bit or 32-bit VMs. As with the empty text,
this array is the value of many empty rulebooks: rulebook arrays are
read-only, so there is no risk of a clash.

@c
Array EMPTY_RULEBOOK -> $ff $ff $ff $ff;

@p Empty Set.
The falsity proposition describes the empty set of objects, and is the
zero value for the ``description'' kind of value.

@c
[ Prop_Falsity reason obj; return 0; ];

@p 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.

@c
{-call:Data::Tables::compile_max_score}
#Ifndef MAX_SCORE;
Global MAX_SCORE = 0;
#Endif;

@p 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.

@c
Attribute absent; ! Used to mark objects removed from play
Attribute animate; ! I6-level marker for I7 kind "person"
Attribute clothing; ! = I7 "wearable"
Attribute concealed; ! = I7 "undescribed"
Attribute container; ! I6-level marker for I7 kind "container"
Attribute door; ! I6-level marker for I7 kind "door"
Attribute edible; ! = I7 "edible" vs "inedible"
Attribute enterable; ! = I7 "enterable"
Attribute light; ! = I7 "lighted" vs "dark"
Attribute lockable; ! = I7 "lockable"
Attribute locked; ! = I7 "locked"
Attribute moved; ! = I7 "handled"
Attribute on; ! = I7 "switched on" vs "switched off"
Attribute open; ! = I7 "open" vs "closed"
Attribute openable; ! = I7 "openable"
Attribute scenery; ! = I7 "scenery"
Attribute static; ! = I7 "fixed in place" vs "portable"
Attribute supporter; ! I6-level marker for I7 kind "supporter"
Attribute switchable; ! I6-level marker for I7 kind "device"
Attribute talkable; ! Not currently used by I7, but retained for possible future use
Attribute transparent; ! = I7 "transparent" vs "opaque"
Attribute visited; ! = I7 "visited"
Attribute worn; ! marks that an object tree edge represents wearing

Attribute male; ! not directly used by I7, but available for languages with genders
Attribute female; ! = I7 "female" vs "male"
Attribute neuter; ! = I7 "neuter"
Attribute pluralname; ! = I7 "plural-named"
Attribute proper; ! = I7 "proper-named"
Attribute remove_proper; ! remember to remove proper again when using ChangePlayer next

Attribute privately_named; ! New in I7
Attribute mentioned; ! New in I7
Attribute pushable; ! New in I7

Attribute mark_as_room; ! Used in I7 to speed up testing "ofclass K1_room"
Attribute mark_as_thing; ! Used in I7 to speed up testing "ofclass K2_thing"

Attribute workflag; ! = I7 "marked for listing", but basically temporary workspace 
Attribute workflag2; ! new in I7 and also temporary workspace
Constant list_filter_permits = privately_named; ! another I7 listwriter convenience

@p 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.

@c
Property add_to_scope; ! used as in I6 to place component parts in scope
Property article "a"; ! used as in I6 to implement articles
Property capacity 100; ! = I7 "carrying capacity"
Property component_child; ! new in I7: forest structure holding "part of" relation
Property component_parent; ! new in I7
Property component_sibling; ! new in I7
Property description; ! = I7 "description"
Property door_dir; ! used to implement two-sided doors, but holds direction object, not a property
Property door_to; ! used as in I6 to implement two-sided doors
Property found_in; ! used as in I6 to implement two-sided doors and backdrops
Property initial; ! = I7 "initial description"
Property list_together; ! used as in I6 to implement "grouping together" activity
Property map_region; ! new in I7
Property parse_name 0; ! used as in I6 to implement "Understand... as..." grammars
Property plural; ! used as in I6 to implement plural names for duplicate objects
Property regional_found_in; ! new in I7
Property room_index; ! new in I7: storage for route-finding
Property short_name 0; ! = I7 "printed name"
Property vector; ! new in I7: storage for route-finding
Property with_key; ! = I7 "matching key"

Property KD_Count; ! Instance count of the kind of the current object
Property IK1_Count; ! These are instance counts within kinds K1, K2, ...
Property IK2_Count; ! and it is efficient to declare the common ones with Property
Property IK4_Count; ! since this results in a slightly smaller story file
Property IK5_Count;
Property IK6_Count;
Property IK8_Count;

Property IK1_link; ! These are for linked lists used to make searches faster
Property IK2_link; ! and again it's memory-efficient to declare the common ones
Property IK5_link; ! 
Property IK6_link; ! 
Property IK8_link; ! 

Property articles; ! not used by I7, but an interesting hook in the parser
Property grammar; ! not used by I7, but an interesting hook in the parser
Property inside_description; ! not used by I7, but an interesting hook in the locale code
Property short_name_indef 0; ! not used by I7, but an interesting hook in the listmaker

@p 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.)

@c
Constant life = NULL;

@p Action Count.
The number of valid I7 actions in existence.

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

@p 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 {\it 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|.

@c
Fake_Action ListMiscellany;
Fake_Action Miscellany;
Fake_Action PluralFound;
Fake_Action TheSame;
