Nested If Statements, Multiple Objects

Hi All

I’ve recently rediscovered the joys of IF (used to use the Graphic Adventure Creator on the C64 when I was a kid!) and have started on my first forays into writing using Inform 7. However, there are a few things I’m trying to achieve that seem to be fairly standard IF practice IMHO, but I’m having a hard time working out how to implement in Inform.

Apologies if this has already been covered - I did some searching around but couldn’t find anything specific…

Issue 1: Nested If Statements

So, I’m currently working on the usual ‘dungeon’ style scenario and I’ve given the player a beastie to fight. I want the player to trigger an event with several possible outcomes using ‘Attack [monster]’. The outcomes are determined by checking the equipment the player is carrying.

Currently I’ve written the following:

Before attacking the [monster]: begin; if the player is carrying the [item]: begin; say "You brutally hack at the [monster] until it is an unrecognisable pulp. By some magickal means the slimy puddle left behind morphs into a brass key."; move [monster] to the void; move brass key to location; otherwise; say "The [monster] waves it's antennae menacingly. You decide you'd be better not messing with this one."; end action; end if; end if;

(I’ve replaced monster and item names so as not to give away to much in case this becomes the next IF sensation, haha.)

Of course, this is generating the following error:

Wat do?

Issue 2 - Multiple Objects

In another scenario I’ve set up a storehouse where a number of items are kept. Some of the items in the storehouse come in multiples, but the player only needs to take one at any given time.

I’ve read the documentation which describes making an ‘infinite’ item dispenser which only gives the item if the player doesn’t have one, but I don’t want to use this method - I want to put, for example, five batteries into the storehouse and give the option of taking one or more batteries if they choose to.

I’ve managed to put the five batteries in place but I can’t find out how to make the player take a single battery. Any clues?

Thanks a lot for any help you guys can give!

I can’t help you with the first question, because I use the tab stops conditional syntax and I don’t know how the begin/end one works, but for the second question, one way you could do it is by making a battery kind. You would say: A battery is a kind of thing. The plural of battery is batteries. Five batteries are in the Storehouse.

See Chapter 4.13, “Duplicates” for more information (and 4.4 about plurals for kinds; I’m not sure if I needed to teach Inform the plural of “battery,” but it can’t hurt).

You’ve got the begin/end if style a little off, and it isn’t even an example of nested IF statements.

Here’s how it should look if you want to do it your way:

Before attacking the monster: if the player is carrying the item begin; say "You brutally hack at the [monster] until it is an unrecognisable pulp. By some magickal means the slimy puddle left behind morphs into a brass key."; move monster to the void; move brass key to location; stop the action; otherwise; say "The [monster] waves it's antennae menacingly. You decide you'd be better not messing with this one." instead; end if.

Here’s how it should look with something more akin to best practice:

The block attacking rule is not listed in the check attacking rulebook.

Check attacking the monster:
if the player is not carrying the item, say "The [monster] waves it's antennae menacingly. You decide you'd be better not messing with this one." instead.

Carry out attacking the monster:
move brass key to location.

After attacking the monster:
say "You brutally hack at the [monster] until it is an unrecognisable pulp. By some magickal means the slimy puddle left behind morphs into a brass key.";
move monster to the void.

Report attacking:
say "Violence isn't the answer to this problem.".

Attacking is blocked by default by core rules. You should unlist it if you want attacking to feature in the game. Under Index/Actions you can see a list of actions included by default, from here you can unlist the rules that block them doing anything.

Good luck!

Your use of brackets makes me wonder whether a monster in your game is a thing or a kind. If it is a kind, beware of any time you type the words “the monster” - it almost never does what you mean, since it’s parsed by the compiler as “a monster.” If I’m reading your code correctly, changing it to “the noun” will do what you intend.

I agree with Joey that a Before rule isn’t what you want here, but you needn’t go all the way towards implementing separate check/carry out/report rules - an Instead rule might be fine.

An instead rule would do it, but then the action would count internally as a failure, which can cause issues further down the line.

Also I think generally its a pretty bizarre programming tactic to define an action and then say to do something instead of that action; it’s like, ‘This is attacking, but instead of attacking do this stuff which is functionally equivalent of attacking!’

If you don’t use an instead rule, the key thing is that the monster (which I assume is being used as a place holder here) is sent to the void after the action is resolved.

If you’re creating a whole kind of thing (a monster) which are all affected in the same way by the attack command, then yes, this makes sense. But if there is only one monster in the game, or every monster requires unique code to respond properly to >ATTACK IT, then you almost certainly want to use Instead or After rules. See WI 12.2:

If you don’t want to use an Instead rule to handle a case where the action technically succeeds, then After will work fine (after you unlist the block attacking rule and add whatever check and default carry out rules you actually want to use, of course). As the 12.2 diagram indicates, an After rule will preempt the default Report message that would ordinarily be displayed for the successful action.

(Yes, I realize there’s often no functional difference between defining certain code as Before or Instead vs Check or Carry Out, or After vs Report. But there very well could be; note that Before doesn’t test visibility or accessibility, while Check does; Report rules are not followed for “try silently” actions, while After rules are; and so on.

And less obviously, but perhaps more importantly, the standard and expected procedure is to place the one-off, special-case responses to actions in the Before, Instead, and After rulebooks, while the Check, Carry Out, and Report rulebooks are reserved for standard, ordinary functionality. Putting different kinds of rules in a rulebook than what it was designed for may interact with some other code of yours, others’ code (extensions), or even the standard rules in unexpected ways, resulting in very hard-to-trace bugs.)

Good post ChrisC,

these things (if you ask me) are the hardest things to figure out in Inform7. Often there are several ways to do something, and it’s often hard to tell whether the choice is just a matter of style or if really matters.

That’s fair.

Or, I would say, “does it matter to me.” Most often the answer is that it can be important, but only if you are doing certain things in your game, and you might not be.

(For example, I typically don’t rely on action-success flags in my code.)

There’s a range of debugging tools that can help with action problems.

The debugging commands “actions” and “rules” can tell you which actions and rules are running. If you use “rules all,” you’ll also get a list of some rules that don’t apply (not all, I think), and some other details.

The Index has a section for Actions where you can check the order of Check, Carry Out and Report rules, as well as information about how actions are parsed. The Rules tab includes the Before, Instead and After rulebooks. The Index is the ultimate authority on how rules end up being ordered.

Finally, there’s good old print statements (e.g. say phrases). Inform also has a handy “showme” phrase that can let you inspect an expression:

First does the player mean: showme the current action.