| What's New in Inform 5.5, v1502 | |
| ------------------------------- | |
| (5 July 1995) | |
| Version 5.5 is the first upgrade of the Inform compiler to provide new | |
| features (rather than just fix bugs) for about 10 months. | |
| For the last year or so, my intention has been to keep the Inform language | |
| stable, but to continually enhance the library. Although these additions do | |
| change the language, they are hopefully minor and logical, and several have | |
| long been asked for. Inform 5.5 removes no features of 5.4 (except in so | |
| far as it tests for a few more definite errors, so some old but subtly wrong | |
| code may not compile: this is probably a good thing). However, it does now | |
| produce warnings if the source code uses obselete features (leftovers from | |
| Inform 1 right up to those from Inform 5.4). The new syntax is so much | |
| nicer that I suggest changing over to it rather than switching off these | |
| warnings at the command line. | |
| The short answer is: tidier object-name printing, more logical and flexible | |
| syntax for creating arrays, tables of data, slightly better grammar | |
| replacement, a switch statement and provision for compiling very much larger | |
| games (up to twice the size of the previous maximum, which was pretty huge | |
| anyway). | |
| *** It is recommended that Inform 5.5 should only be used with *** | |
| *** library release 5/10 and later *** | |
| (there was a minor bug in 5/9 which can cause compilation errors: an | |
| example of "old but subtly wrong code"). In any case, accompanying this | |
| release is library 5/11. | |
| 0. Bugs fixed from v1405 (all minor) | |
| ------------------------------------- | |
| (a) comments caused problems when coming between a loop construct (e.g. | |
| "for (i=1:i<10:i++)") and its block of code. | |
| (b) using the "box" command inside an embedded routine (which is seldom | |
| sensible, actually!) sometimes produced mysterious compilation errors. | |
| (c) the code for explicitly-defined string constants, such as | |
| Constant Game "Lost Trifles of Bluffocom"; | |
| has been thoroughly rewritten, since the old method produced wrong | |
| results in some cases (such as if a global variable had been | |
| given as initial value a string, e.g. by: global Var="hello";). | |
| (d) initial values like strings and dictionary words for global variables | |
| (at declaration time) now work properly. | |
| (e) removal of a foolish restriction rather than bug: string constants | |
| had to be preceded by a # in usage, (e.g. print #Dragons_Name;) for no | |
| good reason. (E.g., print Dragons_Name; now works.) | |
| (f) the #r$RoutineName construction didn't work when RoutineName was | |
| within the first 256 bytes of the code area (only library internals live | |
| there, and this bug has never been observed in honest code!) | |
| (g) actually, this is the same as in v. 5.4, but I seem to have forgotten | |
| to publicise it: the function indirect(R); (to call the function with | |
| address R, so for instance indirect(#r$MyFunction)) can now take an optional | |
| second and third argument. indirect(R,x); calls function R with one | |
| parameter, x, and indirect(R,x,y); calls it with two, x and y. | |
| (h) the notoriously unhelpful (though happily rare) "a label has moved | |
| between passes" error message has been rewritten to suggest the likely | |
| cause: it now reads | |
| An error has occurred just before this point with what Inform | |
| thought was a constant. Perhaps it was a global variable used | |
| before its definition in the code. | |
| (i) local variables can't be called "sp" (this is the name of the stack | |
| pointer, so crashes result) and an error is now produced if they are. | |
| 0'. Bugs fixed in, and additions made to, the beta-version | |
| ----------------------------------------------------------- | |
| A beta-testing version of Inform 5.5 was (silently by me) put onto the | |
| archive for porters to experiment with (though in the event many other | |
| people found it). This version, v1501, included a serious bug (l) and | |
| several improvements have been made since: | |
| (j) the assembly opcode @set_colour now works (actually, this bug is a | |
| year old, and was simultaneously found by two different people in the last | |
| couple of months). | |
| (k) values in switch statements are now allowed to take the form "x to y" | |
| (for x<=v<=y), stolen from Modula-3 at Gareth Rees's suggestion. | |
| (l) a bug in final file output caused incorrect game files to be | |
| produced if no version-number had been explicitly set (it now by default | |
| produces legal V5 files). | |
| (m) details for the VMS port (for VAX or Alpha), the Linux, OS/2 and | |
| Mac ports have been updated; the latter now includes a Macintosh | |
| Programmer's Workshop version. | |
| (n) it's difficult to compile dictionary words which contain apostrophes | |
| (e.g., words such as "jemima's") as constants under I5.4; under I5.5, | |
| apostrophes ' in dictionary words should now always be written with an ^. | |
| For example, the constant 'isaac^s' refers to the word "isaac's". | |
| (o) if you specify a property in an object description but give it no | |
| data values, I5.5 now supplies a 0 word as value (5.4 used to compile an | |
| empty list, which was logical but apt to confuse the interpreter). | |
| (p) the grammar enhancements in (10) below were added. | |
| (q) different file extensions for all of V3 to V8 inclusive can now be | |
| made, if the port makes suitable #defines in header.h. | |
| (r) giving a non-default output filename at the command line didn't | |
| work in v1501, owing to a foolish bug. | |
| (s) fuller details are given below of the V8 alterations needed to | |
| "Zip". | |
| (t) overflow of the buffer used for text-transcription (to make "proofs" | |
| of the text in a game) is now checked for; previously this might have | |
| caused memory (typically the symbols table) to be corrupted on very large | |
| games when compiling with -r set. | |
| 1. Printing | |
| ------------ | |
| Recall that the "print" and "print_ret" commands take a list of items, | |
| separated by commas, printing each in turn. (The latter then prints a | |
| new-line and returns true.) The new preferred syntax for these items is one | |
| of: | |
| <expression> print this number | |
| "string" print this string | |
| char <expression> print the character this is the ASCII code of | |
| object <expression> print the given object's true short name | |
| (this shouldn't be used except by the Library, | |
| as it will fail to notice the short_name routines | |
| many objects provide) | |
| (the) expression the definite article and short-name of this object | |
| (The) expression the same, but capitalising the definite article | |
| (a) expression the indefinite article and short-name | |
| (name) expression just the short-name | |
| (char) expression same as print char, for consistency | |
| (number) expression print the number but in words, not numerals | |
| (string) expression print the string at this (packed) address: good | |
| for printing out property values which are | |
| strings in double-quotes | |
| (address) expression print the string at this byte address: good | |
| for printing out dictionary words and little else | |
| (Routine) expression print nothing: but call Routine(expression) | |
| in the expectation that it will print something | |
| These new features are cosmetic, but considerably tidy the look of code. | |
| E.g., one would write | |
| print_ret (The) x1, " explodes messily. Perhaps it was unwise to \ | |
| drop it into ", (the) x2, "."; | |
| to produce, say, | |
| The hand grenade explodes messily. Perhaps it was unwise to drop | |
| it into the glassworks. | |
| whereas in 5.4 it would have to have been | |
| CDefArt(x1); print " explodes messily. Perhaps it was unwise to \ | |
| drop it into "; DefArt(x2); "."; | |
| 2. Global variables, tables and arrays | |
| --------------------------------------- | |
| The whole syntax for declaring global variables has been tidied up and | |
| extended. The new syntax for declaring a variable "frotz" is: | |
| Global frotz; Ordinary variable, set to 0 | |
| Global frotz = <value>; ..., set to this value | |
| Global frotz <array-type> <array-data>; | |
| But since one very rarely wants to change the value of "frotz" in this case | |
| (it will remain the address of the array throughout the game), the more usual | |
| course is to declare | |
| Array frotz <array-type> <array-data>; | |
| which is identical in effect, except that "frotz" is now a constant. (This | |
| can be convenient: it can now be quoted in other array definitions, for | |
| instance, or as a property value.) | |
| There are four types of array: | |
| Syntax Pronounced Contents | |
| -> byte array with entries written array->0 up to array->(n-1) | |
| (can hold chars and numbers between 0 and 255) | |
| --> word array with entries array-->0 up to array-->(n-1) | |
| (can hold any Inform number) | |
| string string a byte array, in which byte 0 holds the number of | |
| data entries in the array | |
| table table a word array, in which word 0 holds the number of | |
| data entries in the array | |
| The array data can also be given in several ways: | |
| a single value - allocate this many zero entries; | |
| two or more values (divided by spaces) - these are the entries; | |
| a string in double-quotes - the entries are the ASCII values of the | |
| characters of this string, in sequence; | |
| or, as | |
| [; <value-1>; ....; <value-n>; ]; | |
| which makes the entries these given values. Semicolons in between the braces | |
| are ignored. (The usefulness of this is that very long declarations, which | |
| would otherwise overflow Inform source code lines, can be made.) | |
| These initial values can be any legal constant (for the first time this | |
| allows dictionary words and routine names): e.g., | |
| 105 "a quoted string" 'c' 'dictionary' #r$RoutineName | |
| For instance, | |
| Array frotz -> 20; | |
| makes an array of 20 bytes, entries of which can be read or written as | |
| frotz->0 ... frotz->19. The initial values are all zero. Whereas: | |
| Array frotz -> 4 8 12 16 20; | |
| makes an array of 5 bytes, initially holding these five values. | |
| Array colours --> "Red" "Yellow" "Blue"; | |
| ... | |
| print (string) colours-->1; | |
| will print "Yellow". | |
| Array frotz string "blorple"; | |
| makes frotz point to an array with contents | |
| 7 'b' 'l' 'o' 'r' 'p' 'l' 'e' | |
| (This differs from Array frotz -> "blorple" in creating the initial 7.) | |
| A typical large table might have the form of: | |
| Array Holidays table | |
| [; "New Year's Day" "Twelfth Night"; | |
| "Ash Wednesday" "Good Friday"; | |
| "Martin Luther King Day"; | |
| ]; | |
| For instance, the names of songs played by the radio in "Curses" occupies a | |
| (pretty enormous) table, and | |
| print (string) RadioSongs-->(random(RadioSongs-->0)); | |
| prints out a random name from it. | |
| In older versions of Inform the keywords "data", "initial" and "initstr" | |
| would have been used to initialise byte arrays suitably, and (annoyingly) | |
| word arrays couldn't be initialised to non-zero values at all. These | |
| keywords still work, but are no longer needed. | |
| 3. Function calls | |
| ------------------ | |
| Can now take up to 7 arguments, instead of being restricted to 3. | |
| (Except in version-3 games, but I hope everyone's gone over to Advanced | |
| (version-5) now.) | |
| 4. Switch statements | |
| --------------------- | |
| Inform now has a "switch" statement similar to that of C. That is, | |
| switch(expression) | |
| { value1: ... | |
| value2: ... | |
| ... | |
| default: ... | |
| } | |
| evaluates the expression, and executes the first ... code if it has value1, | |
| the second ... if it has value2, and so on: if it has none of the values | |
| given, the default ... code is run. (The "default" clause is optional, | |
| but if present must be the last clause.) | |
| (Unlike in C, there is no "case fall-through"; that is, once the value1 | |
| code is executed, control automatically resumes from after the end of the | |
| switch statement.) | |
| Each value can in fact be a list of values, comma-separated. A value | |
| can either be a single Inform constant or something in the form | |
| constant1 to constant2 | |
| (the range being inclusive). So, for example: | |
| switch(random(6)) | |
| { 1: "A snake slithers."; | |
| 2 to 4: "An elephant bellows."; | |
| default: "The jungle is ominously silent."; | |
| } | |
| The "default" clause can now also be put into embedded routines, like | |
| before rules. So, for instance, a room can have the "before" value | |
| before | |
| [; Jump: "The ceiling is too low."; | |
| Look, Inv, Wait: ; | |
| default: "An invisible force holds you inactive."; | |
| ]; | |
| and the "default" rule is run if none of the others are. Note that the | |
| Look, Inv and Wait actions are unaffected as we have explicitly done nothing | |
| to them. | |
| 5. Abbreviate directive | |
| ------------------------ | |
| The Abbreviate directive can now take a list of abbreviation strings, not | |
| just one at a time (and this saves writing out "Abbreviate" 64 times). E.g. | |
| Abbreviate | |
| ". " ", " " the " "The" "You" "ing" "you" "and" "ight" "with" | |
| "all" "'s no" "which" "It is" " th" " no" "t o" "e s" "e i" | |
| " to" "e o" "e a" " ma" "t i" " fi" "e w" " for" " con" " ba" | |
| "d o" " ro" " di" " can" " lo" "t s" "t w" " com" " ho" | |
| " ga" "tion" " from" " ha" "ter" " ea" "This" " hi" " pr" " un" | |
| "d s" " fa" "urs" "'s ~" " ex" "der" "d a" " gr" " cl" | |
| "d i" " po" " door" "her" " a "; | |
| is a plausible set of abbreviation strings, saving about 20K on a 256K game | |
| file when Inform is compiling with the "economy" switch -e set. | |
| 6. Testing the version number | |
| ------------------------------ | |
| A special rule now applies to the Ifdef directive. | |
| #Ifdef VN_****; | |
| ... | |
| #Endif; | |
| where **** is the four-digit number n, will now compile the code ... exactly | |
| if the current Inform version number is at least n. Thus, | |
| #Ifdef VN_1501; print "The all new Inform show!^"; #Endif; | |
| compiles only under this and later updates. | |
| 7. More flexible < > construct | |
| ------------------------------- | |
| Previously, constructions like | |
| <Action noun second>; | |
| were rather restricted, in that Action always had to be an action name | |
| and noun and second couldn't be compound expressions. The latter restriction | |
| is now removed, and the former almost so: if Action is given in brackets | |
| (...) then it's worked out as an expression in the usual way. (Brackets | |
| are needed to tell Inform that the first word shouldn't be tested as a | |
| constant with ## in front, which is what it does with action names.) So, | |
| for instance, | |
| << (magic_action(frotz_spell)) noun.door_dir memory.number >>; | |
| will now compile. All previously-allowed < > and << >> expressions should | |
| compile just as they always did. | |
| 8. Versions 7 and 8 | |
| -------------------- | |
| Two new types of story file are implemented: versions 7 and 8, newly | |
| created for the purpose. (Inform can produce version 6, but this isn't | |
| recommended for text-only games as version 6 is very hard to fully interpret | |
| because of complex graphical features.) | |
| Version 8 is the one recommended for use, if a game of over 256K is | |
| required: it runs up to 512K in length. Inform syntax is fully portable | |
| between version-5 (the default) and version-8; all you need to do is to | |
| compile with -v8 set. | |
| At present versions 7 and 8 are not interpreted by the interpreters in | |
| public circulation. However, V8 is particularly easy to add to Mark | |
| Howell's "Zip" interpreter; see the end of this file. A fairly large V8 | |
| file (a V8 form of the author's new game "Jigsaw") will soon be available | |
| for experiment. | |
| Support for these new versions should percolate through the public domain | |
| in due course, since it's so easily coded, but if you're in a hurry you need | |
| only distribute your game with a suitably doctored interpreter. | |
| It should be added that a 512K Inform game would be gargantuan, 2.5 times | |
| the size of "Curses" (which is itself large as games go) - easily large | |
| enough to code the entire Zork and Enchanter trilogies into one. | |
| 9. At the command line, and file inclusion | |
| ------------------------------------------- | |
| Apart from -v8 (and -v7), there are two new command line switches: to | |
| change the error message style to Microsoft standard format, and to suppress | |
| warnings about obselete usages. | |
| There is one new memory command, $huge, which is an abbreviation for | |
| lots of large memory settings and saves bother when games have become pretty | |
| enormous. | |
| If a command line argument begins with a plus sign +, then the rest of that | |
| word is taken to be a directory in which the Library can be found. (This is | |
| convenient so that only one copy of the Library need be kept, which several | |
| projects in different directories can make use of.) E.g., I use something | |
| like | |
| inform -Tdcx $huge +Library curses/curses games/curses.z5 | |
| The Include directive has a convenient new feature: if the file-name to | |
| include begins with a >, like so | |
| Include ">endgame"; | |
| then the file "endgame" is sought from the same directory as the one doing | |
| the inclusion. (Otherwise, if it has a / in, it's treated literally, and if | |
| not it's sought from the library directory.) This is much less trouble | |
| when a game's source code is segmented into many files, as it usually is | |
| for large projects. | |
| 10. Grammar replacement | |
| ------------------------ | |
| In library grammar, some verbs have many synonyms: for instance, | |
| "attack" "break" "smash" "hit" "fight" "wreck" "crack" | |
| "destroy" "murder" "kill" "torture" "punch" "thump" | |
| are all treated as identical. But you might want to distinguish between | |
| murder and lesser crimes. For this, try | |
| Extend only "murder" "kill" replace | |
| * animate -> Murder; | |
| The keyword 'only' tells Inform to extract the two verbs "murder" and | |
| "kill". These then become a new verb which is initially an identical copy | |
| of the old one, but then 'replace' tells Inform to throw that away in favour | |
| of an entirely new grammar. | |
| Similarly, | |
| Extend only "get" * "with" "it" -> Sing; | |
| makes "get" behave exactly like "take" (as usual) except that it also | |
| recognises "with it", so that "get with it" makes the player sing but "take | |
| with it" doesn't. | |
| You can now also add new verb synonyms. For instance, | |
| Verb "acquire" "grab" = "take"; | |
| gives the "take" verb two new synonyms. | |
| Appendix: Adding Version 8 support to the "Zip" interpreter | |
| ----------------------------------------------------------- | |
| Only one routine need be changed, "configure". In my copy of the source (10 | |
| March 93) it now looks as below (note that in my copy only one if statement | |
| has been added). | |
| /* | |
| * configure | |
| * | |
| * Initialise global and type specific variables. | |
| * | |
| */ | |
| #ifdef __STDC__ | |
| static void configure (zbyte_t min_version, zbyte_t max_version) | |
| #else | |
| static void configure (min_version, max_version) | |
| zbyte_t min_version; | |
| zbyte_t max_version; | |
| #endif | |
| { | |
| zbyte_t header[PAGE_SIZE]; | |
| read_page (0, header); | |
| datap = header; | |
| h_type = get_byte (H_TYPE); | |
| if (h_type < V4) { | |
| story_scaler = 2; | |
| story_shift = 1; | |
| property_mask = P3_MAX_PROPERTIES - 1; | |
| property_size_mask = 0xe0; | |
| } else { | |
| story_scaler = 4; | |
| story_shift = 2; | |
| property_mask = P4_MAX_PROPERTIES - 1; | |
| property_size_mask = 0x3f; | |
| } | |
| if (h_type == 8) /* This is my amendment for V8... */ | |
| { h_type=V5; | |
| story_scaler = 8; | |
| story_shift = 3; | |
| } /* ...ending here. */ | |
| if (h_type < min_version || h_type > max_version | |
| || (get_byte (H_CONFIG) & CONFIG_BYTE_SWAPPED)) | |
| fatal ("wrong game or version"); | |
| h_config = get_byte (H_CONFIG); | |
| h_version = get_word (H_VERSION); | |
| h_data_size = get_word (H_DATA_SIZE); | |
| h_start_pc = get_word (H_START_PC); | |
| h_words_offset = get_word (H_WORDS_OFFSET); | |
| h_objects_offset = get_word (H_OBJECTS_OFFSET); | |
| h_globals_offset = get_word (H_GLOBALS_OFFSET); | |
| h_restart_size = get_word (H_RESTART_SIZE); | |
| h_flags = get_word (H_FLAGS); | |
| h_synonyms_offset = get_word (H_SYNONYMS_OFFSET); | |
| h_file_size = get_word (H_FILE_SIZE); | |
| if (h_file_size == 0) | |
| h_file_size = get_story_size (); | |
| h_checksum = get_word (H_CHECKSUM); | |
| h_alternate_alphabet_offset = get_word (H_ALTERNATE_ALPHABET_OFFSET); | |
| datap = NULL; | |
| }/* configure */ | |
Xet Storage Details
- Size:
- 20.7 kB
- Xet hash:
- 6505e4bfe962d3e0585693a67f36dc6cc0981fbbee0af3cd0846e5da10de68ac
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.