A Guide to Kits. Provisional documentation on how to make and build new kits. @h Historical note. Inform 7 projects have always needed an underpinning of low-level code, in the same way that all C programs can use standard library functions like |printf|. In builds from 2016 and earlier, this standard low-level code was provided as a set of "template files" with filenames like |Mathematics.i6t|, all written in Inform 6. During compilation, an I7 source text would be compiled down to one wodge of I6 code, then standing I6 code from files like |Mathematics.i6t| would be spliced in, and the result would, of course, be an I6 program. With the arrival of Inter and the possibility of compiling to, say, C instead of I6 code, this all conceptually changed. Instead of an undifferentiated mass of template files, that standing material was grouped together into multiple "kits". (The material formerly in "Mathematics.i6t" now lives on inside BasicInformKit.) Moreover, that material is still written in Inform 6 syntax, or very nearly so. What happens to it is completely different -- it is compiled first to Inter, and then to whatever we like, which may or may not be Inform 6 code -- but in practice it is not hard to convert template files to become new kits. The notes in this section are provisional documentation on how to make and use non-standard kits, that is, kits not supplied with the standard Inform apps. @h Exactly how kit dependencies are worked out. Inbuild is in charge of deciding which kits a project will use, just as it also decides which extensions. For an English-language work of interactive fiction being made with the Inform apps, the kits will always be: = (text) BasicInformKit + EnglishLanguageKit + WorldModelKit + CommandParserKit = However, if the "Basic Inform" checkbox is ticked on the Settings panel for the project, the kits will instead be: = (text) BasicInformKit + EnglishLanguageKit + BasicInformExtrasKit = And these are also the defaults when Inform projects are compiled from the command line, with the optional |-basic| switch forcing us into the second case. As a first step, then, let us see why these are the defaults. @ BasicInformKit is absolutely obligatory. No Inform project can ever compile without it: it contains essential functions such as |BlkValueCreate| or |IntegerDivide|. Inbuild therefore makes every Inform project have BasicInformKit as a dependency. Inbuild also makes each project dependent on the language kit for whatever language bundle it is using. The name of the necessary kit can be specified in the language bundle's |about.txt| file -- see //supervisor: Language Services// -- or, if the |about.txt| doesn't specify one, it's made by adding |LanguageKit| to the language's name. So if the French language bundle is used, then the default configurations become: = (text) BasicInformKit + FrenchLanguageKit + WorldModelKit + CommandParserKit BasicInformKit + FrenchLanguageKit + BasicInformExtrasKit = Next, Inbuild adds a dependency on any kit which is named at the command line using the |-kit| switch. Note that this exists as a command-line switch for both |inbuild| and |inform7|. Finally, Inbuild adds an automatic dependency on CommandParserKit if neither the |-kit| nor |-basic| switches have been used. The practical effect of that rule is that Inform by default assumes it is making an interactive fiction of some kind, unless explicitly told not to -- by using |-basic| or |-kit|, or by checking the "Basic Inform" checkbox in the apps.[1] [1] Checking this box equates to |-basic|, which in turn is equivalent to specifying |-kit BasicInformKit|. @ Kits have the ability to specify that other kits are automatically added to the project in an ITTT, "if-this-then-that", way. As we shall see, every kit contains a file called |kit_metadata.txt| describing its needs. The metadata for CommandParserKit includes: = (text) dependency: if CommandParserKit then WorldModelKit = This means that any project depending on CommandParserKit automatically depends on WorldModelKit too. BasicInformKit uses this facility as well, but in a negative way. Its own metadata file says: = (text) dependency: if not WorldModelKit then BasicInformExtrasKit = It follows that if WorldModelKit is not present, then BasicInformExtrasKit is automatically added instead. @ Kits can also use their metadata to specify that associated extensions should automatically be loaded into the project.[1] For example, the |kit_metadata.txt| for BasicInformKit includes the lines: = (text) extension: Basic Inform by Graham Nelson extension: English Language by Graham Nelson = [1] This in fact is the mechanism by which Inform decides which extensions should be implicitly included in a project. Other extensions are included only because of explicit "Include..." sentences in the source text. @ As an example, suppose we have a minimal Inform story called "French Laundry", whose source text reads just "The French Laundry is a room." Running Inbuild with the |-build-needs| option shows what is needed to build this project: = (text as ConsoleText) $ inbuild/Tangled/inbuild -project 'French Laundry.inform' -build-needs projectbundle: French Laundry.inform kit: BasicInformKit extension: Basic Inform by Graham Nelson v1 extension: English Language by Graham Nelson v1 kit: CommandParserKit extension: Standard Rules by Graham Nelson v6 kit: WorldModelKit extension: Standard Rules by Graham Nelson v6 language: English kit: EnglishLanguageKit extension: English Language by Graham Nelson v1 = The effect of some of the rules above can be seen here. EnglishLanguageKit is included because of the use of the English language. WorldModelKit is included only because CommandParserKit is there. And the kits between them call for three extensions to be auto-included: Basic Inform, English Language and the Standard Rules. As this shows, the same kit or extension may be needed for multiple reasons. But it is only included once, of course. @ At the command line, either for Inbuild or Inform7, the |-kit| switch can specify alternative kit(s) to use. Note that if any use is made of |-kit| then CommandParserKit and (in consequence) WorldModelKit are no longer auto-included. For example, if |-kit BalloonKit| is specified, then we will end up with: = (text) BasicInformKit + EnglishLanguageKit + BalloonKit + BasicInformExtrasKit = But if |-kit CommandParserKit -kit BalloonKit| is specified, then: = (text) BasicInformKit + EnglishLanguageKit + WorldModelKit + CommandParserKit + BalloonKit = It may seem that if Inform is being used inside the apps, then there is no way to specify non-standard kits. Since the user isn't using the command line, how can the user specify a |-kit|? However, a feature of Inform new in 2022 gets around this. Additional command-line switches for |inbuild| or for |inform7| can be placed in the Materials directory for an Inform project, in files called |inbuild-setting.txt| and |inform7-settings.txt|. For example, suppose we set both[1] of these files to be: = (text) -kit CommandParserKit -kit BalloonKit = And put the following into place: = (text) Exotic.inform Exotic.materials inbuild-settings.txt inform7-settings.txt Inter BalloonKit ... ... = BalloonKit has to be a properly set up kit -- see below; but if so, then when we next look at the build requirements for the project, we see: = (text as ConsoleText) $ inbuild/Tangled/inbuild -project 'French Laundry.inform' -build-needs projectbundle: French Laundry.inform kit: BasicInformKit extension: Basic Inform by Graham Nelson v1 extension: English Language by Graham Nelson v1 kit: CommandParserKit extension: Standard Rules by Graham Nelson v6 kit: WorldModelKit extension: Standard Rules by Graham Nelson v6 kit: BalloonKit language: English kit: EnglishLanguageKit extension: English Language by Graham Nelson v1 = So now BalloonKit is indeed a dependency. See //inbuild: Manual// for the full story on where the compiler expects to find kits, but basically, they're managed much the way extensions are. [1] Both, so that whether the executable looking at the project is inbuild or inform7, it will use the same set of kits. You want this. @ So, then, what actually is a kit? It is stored as a directory whose name is the name of the kit: in the case of our example, that will be |BalloonKit|. This directory contains: (*) Source code. In fact, a kit is also an Inweb literate program, though it is always a deliberately simple one. (Being Inweb-compatible is very convenient, since it means it can be woven into website form. See //BasicInformKit// for an example of the result.) It is simple because it provides only a |Contents.w| page and a |Sections| subdirectory -- it has no manual, chapters, figures, sounds or other paraphernalia. (*) A file called |kit_metadata.txt| describing the kit, its version and its dependencies. (*) Compiled binary Inter files -- but only once the kit has been built. These always have filenames in the shape |arch-A.interb|, where |A| is an architecture; in that way, a kit can contain binary Inter to suit several different architectures. For example, |arch-16d.interb| or |arch-32.interb|. @ The source code is written in Inform 6 syntax.[1] This means that to create or edit kits, you need to be able to write Inform 6 code, but it's a very simple language to learn if all you're doing is writing functions, variables and arrays. For |BalloonKit|, the contents page |BalloonKit/Contents.w| will be: = (text) Title: BalloonKit Author: Joseph-Michel Montgolfier Purpose: Inter-level support for inflating rubber-lined pockets of air. Sections Inflation = So there will be just one section, |BalloonKit/Sections/Inflation.w|, which will read: = (text) Inflation. Vital Inter-level support for those balloons. @h Inflation function. = Constant MAX_SAFE_INFLATION_PUFFS 5; [ InflateBalloon N i; if (N > MAX_SAFE_INFLATION_PUFFS) N = MAX_SAFE_INFLATION_PUFFS; for (i=0: i