Well, I finally sat down a couple nights ago with my design document and started entering some of the code for the first scene of my game, tentatively entitled “Grounded in Space”.
Very quickly, I hit a brick wall which either didn’t exist in the last build of Inform 7, or is something I missed by sheer blind luck in the past.
Here’s the problem: I have a remote control in the game, which has a setting variable attached to it to track its state. The setting is defined like so:
Remote-control-setting is a kind of value. The remote-control-settings are deactivated, low, and high. The remote control is a thing. The remote control has a remote-control-setting. The remote control is low.
So far, so good. Now I write an adaptive description for the remote control:
The description of the remote control is "<blah blah blah>.
There is a dial on the control with three settings: 'off', 'low', and 'high'.
Currently, the dial is set to [remote-control-setting]."This is a bit more simplified than what I did (I wrote a “say” rule to modify how the raw states were printed), but it reproduces the problem.
This code runs through the Inform 7 front-end just fine, but throws incomprehensible Inform 6 errors during the final stage of compilation. After a bit of “golden mean comment debugging” I isolated the code that was causing the problem (the adaptive description above), and made a change that worked to fix the problem:
The description of the remote control is "<blah blah blah>.
There is a dial on the control with three settings: 'off', 'low', and 'high'.
Currently, the dial is set to [remote-control-setting of the remote control]."I had left this out originally because I figured, coming from a C++ background, that there would be some sort of this pointer equivalent involved here — that since this was an adaptive description for the remote control, it would assume that any variable was in the context of the remote control unless otherwise specified.
How wrong I was.
***
Immediately after surmounting this obstacle, I ran smack into another one when trying to implement the “set” action on the remote control.
This problem was more my fault — it was related to the gyrations needed to implement a custom verb. “Setting it to” is a defined verb in the Inform 7 Standard Rules, but by default it’s turned off — it will deny any attempt to set anything to anything.
There are a couple ways around this as I understand things — you can implement ad hoc overrides using “instead” or “before” rules, or you can disable the rule that denies any attempt to set and implement a full set of action rules (check rules, carry out rules, and report rules).
Since there are a couple of other things I was interested in possibly using with the set verb later in the game, I figured I’d go the full command route.
So I disabled the “block setting it to” rule, and tried to reimplement it as follows:
Setting it to is an action with past participle set applying to one thing and one remote-control-value.
I then went through the exercise of adding check and carry out rules that assumed that “the noun” was a thing (in this case, the remote control) and that “the second noun” was a remote-control-value — one of the values I’d declared earlier. Seems reasonable, right?
Well, it did to me also. And apparently to the compiler as well, as this time the code compiled through both phases just fine. But at runtime I got an error when using the command that implied that although the system was reading my command correctly as setting an object to a remote-control-value, the remote-control-value was being silently converted by the system into an object of the same type id as the ordinal value of my remote-control-value!
In other words, if “high” was the third element in the set of remote-control-values, the system was creating an object of type 3, which internally corresponds to the class “Routine” or something like that. In yet other words, it was creating an object that was completely inappropriate and broken.
I never could figure out whether it was even legal to do what I was trying to do; I simply fell back on the original definition of the action and went with “instead of” overrides to control behavior. In the end it worked out cleaner this way anyway, but I can’t help but wonder how in the world I was supposed to do it the other way.
***
These problems weren’t killers, although they did waste a bit of time. What this is demonstrating to me as I’m going is that writing anything nontrivial in Inform 7 is pretty hard, and this is coming from a C++ programmer with coming up on 20 years of professional experience.
The reasons for this are twofold:
- Natural English is ambiguous, particularly with assumptions of context. This makes it difficult to find the “right way” to express what you want to do, leading to the first type of problem. In fact, whenever given a choice in Inform 7 of an English-like or a code-like mechanism, I always use the more code-ish one (Python style if-then blocks FTW).
- Although the documentation has many excellent cookbook-style examples, the meat of how the engine works and what the Standard Rules actually do and how everything links together is hidden away in PDFs that you have to dig around for on the Inform website. If you can find an example in the documentation that fits the bill, wonderful! You’re off and running. If not, you’re out in the cold.
I’m not bagging on the language — I still think it’s wonderful, and very well suited to the task of writing interactive fiction. And the tools are definitely there to do the type of development I’m trying to do; I just don’t have full mastery of them yet.
I am not, however, going to assume in the future that just because the syntax of the language is natural-language-esque, that development is easy. Inform 7 does make it easy to bang out a quick adventure with the standard set of default behaviors, with perhaps a few overrides sprinkled here and there. But if you want to do something complicated, knowing the syntax of the language isn’t enough. You need to know the Standard Rules and the way the rule engine itself operates, and this information is not easy to uncover.
