Most common 'mistakes' and 'crutches' for those starting out with inform 7?

Can you imagine how much easier WHHoGG would have been if I’d known this then? I didn’t have a single normal verb except for EXAMINE in it. I don’t even want to look at all the stuff I did to turn off verbs there.

4 Likes

Well, maybe one day you will, and you can make a post-comp release of it. In fact, I bet if you sat down now it wouldn’t be too bad.

But of course you actually have new stuff to make, and that’s more fun for everyone involved. And you know this now!

One thing I’ve learned when programming I7 is that I’m under no obligation to provide the original Inform experience, especially if that experience was a bug and not a feature … shutting off the more obscure verbs feels at first like you’re not really trying to be thorough, but actually it’s about concentrating on new good stuff. It took me a while to realize that.

5 Likes

So many great tidbits of info popping up in this thread.

I can’t stress enough to new authors how valuable using books, parts, chapters and sections is in making organising and browsing your code so much easier.

My little combat system I started a few weeks ago has grown to around 1400 lines of code and without headings and nested sections, it would have been a nightmare to add and organise what I’d already written.

I think that a lot of the really useful features aren’t immediately obvious to new users because they’re so enamoured with just getting stuck into experimenting that it’s easy to say ‘I’ll get to learning that other stuff some other time’.

3 Likes

Another thing I’ve done that I regretted is making too many kinds and values. I had lots of overlap and keeping track of things was really muddy.

1 Like

I’m sure I’ve probably done the same at times, I’ve had to create variable values for certain things and have it so that that variable is held as a sort of ‘last time this happened that number is X’ which can then be used in a number of instances such as reporting or using for other equations in following actions etc.

Feels a bit hacky but it’s the simplest and least complex way I’ve found to make a lot of attack variables etc work without having to write heaps of individual rules, instead just in the first instance saying that the variable is now ‘this value’ and every other thing that needs to use that same variable again can just reference it. I think of it as like a memory block or some ram dedicated to storing that specific value only.

2 Likes

Yeah, it’s tough to balance “hey, this works and this is good enough” against “hey, I have an intuition I can do things better and maybe simpler.” Especially since the main people working on Inform aren’t paid to do so, and it’s pretty robust as it is, so it can feel awkward asking “Wait! Can’t things be better?”

For instance, @CrocMiam just pointed out you could say “the room gone to” and “the room gone from” in the check rules. Before that, I’d used “location of the player” and “the room noun of location of the player” in this topic.

I’d never have known this if someone else hadn’t asked a question and others hadn’t chipped in. It might not save a ton of energy, but it will save enough!

So while on one hand the perfect can be the enemy of the good, a small pitfall is to default to “this is tangled but I guess it’s good enough for now.”. Sometimes it will have to be. But other times it is well worth asking.

3 Likes

This bit of advice isn’t for people starting out with I7, but if you want to be able to modify existing rules, there’s no substitute for reading through those parts of the Standard Rules themselves. (v10 makes Standard Rules browsing easier, as all the language fundamentals stuff has been moved to Basic Inform.) The rules concerning the built-in actions are nearly all in plain, very readable Inform 7.

The going action has several useful action variables. If you’re modifying the behavior of the examine action, you should know the “examine text printed” variable – it’s simply a truth state that tracks whether there’s been any output – if there has been any, it won’t print the generic “You see nothing special about…” message. So if your custom rule outputs something, it should both set examine text printed to true and come before the “examine undescribed things” rule. The exiting action’s container exited from variable can be useful. (One more action has variables – looking – but their meaning is esoteric.)

And in general, if you’re adding rules to an action, it’s useful to have an idea of what the existing rules are so you have some intuition about whether you’ll need to worry about interactions or ordering. And you’ll end up better able to guess where you have to look to figure out why some given behavior is occurring.

3 Likes

I’ve been a coder for 15+ years and the one true constant in my method of learning, no matter the language/framework/library, is read the source code. It’s harder than reading the documentation but I believe the understanding you get from reading the source unlocks a lot of things.
In this particular case, I recommend reading the “standard rules” extension.
Here’s a link to the code for the going action. You’ll learn that there are more variables than “the room gone to” and “the room gone from”.

This forum is a gold mine. I’ve learned a ton here reading answers to questions I’ve never asked myself. I don’t need it when I read it but it accumulates somewhere in my mind and months later I’m like Neo: “I know kung-fu”.

6 Likes

This is 100% right, and I’d just flag that Zed’s site laying out the Standard Rules is a great resource for this (for all that v10 makes this easier than it was, I at least haven’t found it as easy as Zed’s version).

2 Likes

One thing to watch out for, in my opinion - which is as much about game design as implementation - is to resist the urge to introduce anything new at all. When you have the choice to either unlist an existing rule and rewrite it to fit your mechanics or to rethink your mechanics to match the existing rules, always choose the latter. You might think this is a matter of personal preference, but on closer introspection, it is not, because players like yourself like to see games which react predictably to input, and a big part of this is to follow the conventions, i.e. the standard rules.
This doesn’t diminish Andrew’s argument for switching off commands altogether to save your breath for the important stuff. I’m sure my own output would have been of much higher quality had I heeded his and my own advice above and given up on both existing and additional simulation elements more often.

4 Likes

on a related note, The whatever-rule-name rule does nothing when [particular condition] is really fantastically useful and there are a bunch of times I’ve kicked myself when I realized I’d been doing something cumbersome and complicated involving replacing a rule when all it needed was just a tiny bit of being selectively ignored.

(The foo rule substitutes for the bar rule when [condition] would probably also be very useful if I ever got as far as kicking myself for having forgotten it instead of just persistently forgetting it.)

8 Likes

Wow this seems incredibly useful. I’m guessing this is a compelling reason to name certain rules as well so they can be utilised with something like this. I think I might have some use for this.

2 Likes

Yeah, I didn’t name a lot of rules at first. I didn’t see the point. But then the first time I actually needed to, a bunch of dominoes fell.

I also think some crutches aren’t necessarily bad–they get you going, and later you see why the more general way is best for more ambitious projects. So if you look back and say “boy! That crutch I used was awkward!” don’t waste too much time on it. The next project will go smoother.

It took me a while to come around to how I didn’t need to add as much new stuff as I thought!

I’d add the caveat here that I had a lot of trouble pulling myself away from a main project to open up a sandbox project that tried something new. This has been really valuable to me–a lot of times I got a weird error in a big game, or I didn’t understand how to implement syntax, and I opened up a smaller/blank project and was able to isolate the problem.

You don’t have to reinvent the wheel as much as you think. Smart people ahead of you created inform, and smart people wrote extensions. Smart people wrote in it, too, and they shared the source code, and one big help for me is looking at said source code to see “oh, that’s how someone did things, or did things better than me.”

I have to admit I did! I’ve done so a lot. It’s been really useful for me to poke into I6 as well. But what usually happens is, I wind up poking at what I want and just stopping there. But I think as I learn more I7, the source becomes easier to read, and I never went back to say “OK, that thing that was intimidating once and still feels like it because horizon effect, etc. shouldn’t and doesn’t any more.” So I would add it helps to go back to the source code you cribbed from, to make sure you were doing things right.

I’ve also learned a ton from extensions as well. Once I start using one and wondering “how did they do that?” or “I’d like X, but without the overhead/modified to do Y,” it feels good to be able to build on things.

I know when I dive into a new language I have a fear of not understanding the deeper stuff, but I recognize the worst that happens is, I just don’t understand stuff, but maybe I’m primed for when I have more experience and might understand it later.

3 Likes

I second this. When I was working on Transparent,

Summary

I was working in the Mac IDE during a time where for some reason the troubleshooting jump-arrows were not working.

You know how you see an error and can click to jump there in the code? That didn’t work.

So I had to divide the source text with enough grain so I could read the error and then use the outline filter view to cut the text down to just that section and find the error.

It also trained me to keep random rules kind of close to the room or concept that they pertained to instead of just adding things to the end of the source all the time.

It’s also quite satisfying when you get to name a section something like “Section 15 - All Right, Fine, Beta Testers, you think it will be fun to set things on fire with the candle?”

2 Likes

One of the easiest pitfalls to repeatedly stumble into is to forget that your are coding a game or interactive story, not a simulation…

If your game requires a car to get you from A to B, it probably needs nothing more complex than for “Enter car. Go North” to work. No need for keys, opening & closing doors, starting & stopping the engine etc. etc. etc.

Furthermore, if there’s a clash between fun game mechanics and realism, always choose the former. Consider the hit-points-based fight mechanics of classical Dungeons & Dragons. Utterly ridiculous from a simulation point of view: People (and monsters) don’t generally succumb in hand-to-hand combat to ‘death from a thousand cuts’. But it works better as an enjoyable approach to risk-taking regarding combat than a more dichotomous but realistic ‘your character will likely die or remain largely unscathed’- albeit this is the situation faced even by a D&D character with a single hit point- which is why many D&D campaigns allow such characters to be re-rolled…

3 Likes

Staying with the car example for a moment, you could of course have the player search the whole house for the key (which obviously involves navigating a remote-controlled robotic mouse under the floorboards), have them fail at opening the driver’s door because it is rusted shut and make them tear down the garage wall at the other side of the car (which is parked too close to it to get in otherwise) using an improvised battering ram before allowing them to enter the car and drive away. One would, naturally, have to keep in mind that while it wouldn’t be necessary to turn the key before going north, the player should be awarded extra points for doing so (and for closing the car door behind them). In the end though, the whole scene would just be another lock-and-key-puzzle and should, for well-known narrative reasons, indeed be cut in its entirety. The story should start on the lonely mountain road after the car has broken down.

3 Likes

Thought of another: if you say

A thing can be dynamic or static.

and don’t specify a default, the default is that it’s not the first thing. Awkward language on purpose to also embrace this case:

A thing can be confiscated. [ by default things are not confiscated. ]

But with enumerated kind of value properties, if you don’t make a default explicit with usually or seldom the default is the first named.

grade-value is a kind of value. The grade-values are A-grade and F-grade.

A person has a grade-value called the grade. [ default grade is A-grade ]

You may well find it easiest to just be sure to always specify the default explicitly than to remember this…

5 Likes

Since this topic popped up, I thought I’d write up one thing I didn’t realize for a long time because I had “good enough I guess.”

Perhaps the silliest thing I did early on was not realizing that repeat loops could have continue; and next;. They seemed to work okay, then one day I needed continue/next type logic, and I did something horrible like

let found-one be a truth state that varies
repeat with x running through touchable things:
    if found-one is false and x is (what we want):
        (do something)
        now found-one is true;

For some reason I just missed something, but then when I read the documentation it was obvious. So as I mentioned above, if you’re just glad something works, it’s worth bookmarking it later to read the relevant documentation, as something might fall out.

The “abide by” syntax was also something I didn’t look at for a while. A lot of times I’d just use the “to do-x:” syntax. And then I had to use some hacky stuff to back out of main rules at first, and eventually I got sick of said hacky stuff or duplicate coding. I wish I’d have gotten sick of it quicker.

Note, for those who don’t know, “abide by” helps avoid duplicating code. Below is pseudocode, but it gives an example.

this is the what can't be moved rule:
    if noun is carried, say "You don't need to." instead;
    if noun is a person, say "You don't want to start any fights." instead;
    if noun is the broken lever, say "The broken lever is broken." instead;
    if noun is the lawnmower, say "The lawnmower is out of gas." instead;
    if noun is the sofa and nickel is off-stage:
        now the player has the nickel;
        say "You find a nickel under the sofa!" instead;

carry out pushing:
    abide by the what can't be moved rule;
    (do the main stuff);

carry out pulling:
    abide by the what can't be moved rule;
    (do the main stuff);

This was one of those things where once I saw it, I felt silly I didn’t find it earlier.

One crutch I still use (I don’t know if there’s a better way) is to have a room called done-room. Then:

to mark-done (th - a thing):
    move th to done-room;

definition: a thing (called th) is done-with:
    if th is in done-room, yes;
    no;

I mention it because at first I would get rid of items by putting them back out of play, which caused problems when I said “if x is off-stage and (search and find x), now player has x”.

3 Likes

I’m trying to get a demo out the door, and I had a really messy verb that I wanted to clean up so that it made more sense on-screen.

Well, I accidentally used “any thing” instead of “something”. Not sure why, I never do that. Anyway, it compiled fine but I started getting run-time errors about various things: variables, disambiguation messages for objects in other rooms, run-time errors.

It’s a busy verb that goes through the whole processing order and, miracle of miracles, it was all coded correctly, but verifying that was impossible because of the errors. I looked at rules, looked at actions. Was stumped. I wasn’t catching on to the “any thing” and “something.” distinction.

Picked the whole process apart, fed it piece by piece into my test project. Started commenting out values because of the error messages. Starting from a mountain (for me, anyway) of code, I whittled it down bit by bit. Finally got to practically nothing:

frobbing is an action applying to one thing.
understand "frob [any thing]" as frobbing.

check frobbing:
	continue the action.

Was still getting disambiguation messages for items in other rooms. I even wrote a rule for stopping actions applying to such objects :stuck_out_tongue:

So. That was last night (NA CST) and I just now fixed it. Feels kind of dumb, but my brain just edited it out.

That’s definitely my biggest mistake so far as a beginner. “Any thing” is serious business.

8 Likes

Wow that would’ve been a great learning experience albeit a frustrating one. So I’m guessing any thing would encompass literally anything vs something which only refers to a thing? This could obviously have very interesting complications depending on the context that any thing is used.

1 Like