/
Story Substrate.i7x
355 lines (239 loc) · 11.5 KB
/
Story Substrate.i7x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
Version 1/200930 of Story Substrate by Jeff Nyman begins here.
"Provides information about the substrate that a story is executing on."
"utilizing some techniques from Interpreter Sniffing by Friends of I7"
Chapter - Serial Number (for Glulx only)
Include (-
[ SerialNumber i;
for (i=0 : i < 6 : i++) print (char) ROM_GAMESERIAL -> i;
];
-).
Chapter - Serial Number (for Z-Machine only)
Include (-
[ SerialNumber i;
for (i=0 : i < 6 : i++) print (char) HDR_GAMESERIAL -> i;
];
-).
Chapter - Serial Number Phrase (unindexed)
To say story serial number: (- SerialNumber(); -).
Chapter - IFID (unindexed)
The print ID number rule translates into I6 as "UUID_R".
Include (-
[ UUID_R ix;
for (ix=6 : ix <= UUID_ARRAY -> 0 : ix++) print (char) UUID_ARRAY -> ix;
];
-).
To say story IFID number: (- UUID_R(); -).
Part - Inform Information
Chapter - I7 (NI) Build (unindexed)
Include (-
[ I7_Build;
print (string) NI_BUILD_COUNT;
];
-).
To say I7 build: (- I7_Build(); -).
Chapter - I6 Build (unindexed)
Include (-
[ I6_Build;
inversion;
];
-).
To say I6 build: (- I6_Build(); -).
Chapter - I6 Library (unindexed)
Include (-
[ I6_Library;
print (string) LibRelease;
];
-).
To say I6 library: (- I6_Library(); -).
Chapter - I7 Identifier (unindexed)
Include (-
[ I7_Identity;
print (string) NI_BUILD_COUNT, " ";
print "(I6/v"; inversion;
print " lib ", (string) LibRelease, ") ";
#ifdef STRICT_MODE;
print "S";
#endif;
#ifdef INFIX;
print "X";
#ifnot;
#ifdef DEBUG;
print "D";
#endif;
];
-).
To say I7 identity: (- I7_Identity(); -).
Part - Interpreter Information (for Glulx only)
Chapter - Bitwise Calculations (unindexed)
Include (-
[ is_logical_right_shift value distance;
@ushiftr value distance sp;
@return sp;
];
-).
To decide what number is the bitwise and of (I - an arithmetic value) and (J - a number):
(- ({I} & {J}) -).
To decide what number is (I - an arithmetic value) logically shifted (D - a number) bit/bits right:
(- is_logical_right_shift({I}, {D}) -).
Chapter - Version Numbers (unindexed)
A terp version number is a kind of value.
65535.255.255 specifies a terp version number.
To say (N - a terp version number):
let the major terp version number be N logically shifted 16 bits right;
let the minor terp version number be the bitwise and of N logically shifted 8 bits right and 255;
let the patch level be the bitwise and of N and 255;
say "[the major terp version number].[no line break][the minor terp version number].[no line break][the patch level]".
Chapter - Glulx Version
Section - Glulx Values
A Glulx implementation is a kind of value.
Unknown Glulx implementation is a Glulx implementation.
Section - Glulx Detected
Glulx implementation already detected is a truth state that varies.
Glulx implementation already detected is false.
The cached result of Glulx implementation detection is a Glulx implementation that varies.
Section - Detecting Glulx (unindexed)
The Glulx implementation detection rulebook is a nothing based rulebook producing a Glulx implementation.
To decide what Glulx implementation is the current Glulx implementation:
if Glulx implementation already detected is false:
now the cached result of Glulx implementation detection is the Glulx implementation produced by the Glulx implementation detection rulebook;
unless the rule succeeded:
now the cached result of Glulx implementation detection is Unknown Glulx implementation;
now Glulx implementation already detected is true;
decide on the cached result of Glulx implementation detection.
Section - Detecting Glulx Version (unindexed)
Include (-
[ is_glulx_version;
@gestalt 0 0 sp;
@return sp;
];
-).
To decide what terp version number is current Glulx version number: (- is_glulx_version() -).
Chapter - Interpreter Version (unindexed)
Include (-
[ is_interpreter_version;
@gestalt 1 0 sp;
@return sp;
];
-).
To decide what terp version number is current interpreter version number: (- is_interpreter_version() -).
Chapter - Glk Test (unindexed)
Include (-
[ is_glk;
@gestalt 4 2 sp;
@return sp;
];
-).
To decide whether the Glk gestalt is set: (- is_glk() -).
Chapter - I/O Version
Section - IO Values
An IO implementation is a kind of value.
Unknown Glk implementation and Unknown non-Glk implementation are IO implementations.
Section - IO Detected (unindexed)
IO implementation already detected is a truth state that varies.
IO implementation already detected is false.
The cached result of IO implementation detection is an IO implementation that varies.
Section - Detecting IO (unindexed)
The IO implementation detection rulebook is a nothing based rulebook producing an IO implementation.
To decide what IO implementation is the current IO implementation:
if IO implementation already detected is false:
now the cached result of IO implementation detection is the IO implementation produced by the IO implementation detection rulebook;
unless the rule succeeded:
if the Glk gestalt is set:
now the cached result of IO implementation detection is Unknown Glk implementation;
otherwise:
now the cached result of IO implementation detection is Unknown non-Glk implementation;
now IO implementation already detected is true;
decide on the cached result of IO implementation detection.
Section - Detecting IO Version (unindexed)
Include (-
[ is_io_version
canGetVersion;
@gestalt 4 2 canGetVersion;
if (~~canGetVersion) {
return 0;
}
return glk_gestalt(gestalt_Version, 0);
];
-).
To decide what terp version number is the current IO version number: (- is_io_version() -).
Part - Specific Glulx Implementation
Chapter - Git
Git Glulx is a Glulx implementation.
Chapter - Git Test (unindexed)
Include (-
[ is_git;
@gestalt 31040 0 sp;
@return sp;
];
-).
To decide whether the Git gestalt is set: (- is_git() -).
Chapter - Git Rule (unindexed)
Glulx implementation detection (this is the test for Git rule):
if the Git gestalt is set:
rule succeeds with result Git Glulx.
Part - Specific Interpreter Implementation
Chapter - Interpreters
An interpreter is a kind of value.
Unknown interpreter is an interpreter.
Git-based interpreter are interpreters.
Section - Determine Interpreter (unindexed)
To decide what interpreter is the current interpreter:
if the current IO implementation is:
-- Unknown Glk implementation:
if the current Glulx implementation is:
-- Git Glulx:
decide on Git-based interpreter;
decide on Unknown interpreter.
Part - Action for Getting Substrate Information
Reporting the substrate is an action out of world.
Understand "show substrate" as reporting the substrate.
Report reporting the substrate:
say "Serial number: [story serial number].";
say "IFID: [story IFID number].";
say "Inform 7 compiler: [I7 build].";
say "Inform 6 compiler: [I6 build].";
say "Inform 6 library: [I6 library].";
say "Inform 7 Identity: [I7 identity].";
say "Glulx version: [current Glulx version number].";
say "Interpreter version: [current interpreter version number].";
say "I/O version: [current IO version number].";
say "Current IO Implementation: [current IO implementation].";
say "Current Glulx Implementation: [current Glulx implementation].";
say "Current Interpreter: [current interpreter]."
Story Substrate ends here.
---- DOCUMENTATION ----
Story files are built on a particular version of Inform 7 which is utilizing a series of extensions to provide functionality. Inform 7 is, in turn, backed up by a version of Inform 6 which is itself using a particular Inform 6 library. Much of this information is printed as part of the "banner" that displays when a story file starts or if a "version" command is used. There may be a desire to get some of that information individually and that's what this extension helps to do.
There is also the interpreter that the story itself is running on. This extension will attempt to gather some of that information, although interpreter information can only be recovered in a Glulx context.
All of this is what I refer to as the "substrate." This extension helps recover and display that information.
Section - Serial Number
To get the serial number:
say "Serial number: [story serial number]."
Section - IFID
IFID stands for Interactive Fiction IDentifier. An IFID is a number that is unique to each story file. This gives players, authors, and archivists a universal and unambiguous way in which to refer to a given story file. The IFID forever refers to that story file in all of its versions, regardless of its serial number, release number and so forth. Conceptually it's pretty much identical to the idea of the ISBN system for books. The IFID system is defined by the Treaty of Babel, which was created in 2006.
To get the IFID:
say "IFID: [story IFID number]."
Section - Inform 7
Inform 7 provides a specific compiler called NI (Natural Inform) which has its own version. To get that version:
say "Inform 7 compiler: [I7 build]."
NI is the Inform 7 compiler that in turn relies on a specific Inform 6 compiler. To get that version:
say "Inform 6 compiler: [I6 build]."
Inform 6 relies on a specific library of code. To get the version of the Inform 6 library:
say "Inform 6 library: [I6 library]."
All of the above translates into what I call the "Inform 7 Identity", meaning that with the above information you can construct a very specific identity for the particular version of Inform that was used to compile a given story file. You can get that full identity with:
say "Inform 7 Identity: [I7 identity]."
This "identity" is essentially what's printed as part of the starting banner. Having a simple way to refer to the string, however, means you can recover it if you decided to override how, or even if, the banner is displayed.
Section - Interpreter Style (Glulx Only)
There have been various ways to get information about the interpreter that the story file is running on. Most of them are imperfect at best so this extension doesn't really try to do much of what's called "interpreter sniffing." These next bits only work under Glulx interpreters.
To get the Glulx verison number that the story is being interpreted under:
say "Glulx version: [current Glulx version number]."
Glulx is the virtual machine, which has its own version number, as distinct from the interpreter that is implementing the virtual machine. To get the Glulx interpreter version number:
say "Interpreter version: [current interpreter version number]."
There is yet one more level to consider which is the I/O implementation being used, which has to do with Glk. This, too, will have its own version. To get the I/O version:
say "I/O version: [current IO version number]."
Whether the above information is useful really depends on whether you are using some effect or feature that is known to exist only within certain Glulx versions or with certain Glk I/O implementations. The interpreter version is less useful without knowing what the actual interpreter is so, for now, that's included for completeness of versioning information rather than as anything terribly useful.
That said, I have implemented those parts of Interpreter Sniffing that attempt to look for the current implemenation of either the IO verison or the Glulx verison. You can have those displayed as such:
say "Current IO Implementation: [current IO implementation].";
say "Current Glulx Implementation: [current Glulx implementation]."
You can try to determine what the current interpreter is by the following:
say "Current Interpreter: [current interpreter]."
However the mechanisms in place to be able to detect are extremely poor, at best. So it's unclear if this is has any real value.