Seeking feedback on coding exercise

Hello! Would anyone be willing to give constructive feedback on my Inform 7 code for a small (one room, one puzzle, winnable in a few minutes) practice game? I’m not looking to perfect this game, but to learn how to code more effectively in the future. The game more or less plays the way it should, but I doubt it always uses the best rules for the job or does things the most efficient way.

Incidentally, what’s the best way to send code to someone without publishing it online? Is it possible to put it into a PM?

Edited to add link: playfic.com/games/ata/coding-exercise
Please feel free to ignore all the changes to the standard library messages at the end. Thanks for any help you can offer!

My Inform’s way too rusty and amateurish to be of any use, but I’d recommend posting your code here in a rant tag, unless you wanted to keep it secret for some reason (I’m guessing not, since it’s a practice game). That way anyone can jump in and offer advice, and the thread could be of use to future readers.

You make a good point about people being able to chime in. I ended up putting it on playfic–will probably not leave it up forever, though.
playfic.com/games/ata/coding-exercise

I’ve already gotten a lot of useful pointers on this forum about changes to the standard library messages. Between that and the changes to the upcoming version of Inform 7, there’s probably no need to comment on those unless you really want to.

I could have something to say about… almost everything in your code. I will try and PM you with a commented version of your game, but I really think it would be useful to publish it here for mainly two reasons:

  1. everybody will see what I have to say, in case it is noteworthy;
  2. everybody will see what I have to say, in case I’m mistaken and they can help me getting better at Inform, too.

What do you think?

In the meanwhile, I’ll copy-paste your project into Inform7.
Brb.

Edit to add: I’m pretty sure that double spaces after a period are deprecated.

James, thank you so much for the comments. Rather than paste the entire code here, I wonder if it would make sense just to post most of the things you commented on or that I had questions about?

James put his comments in [!!!---- ----!!!].

  1. I was splitting the code into sections using comments. James said:
    [rant][!!!----Why don’t you use Chapters and Sections instead of Comments? The source code would be splitted for better control ----- CHECK THE CONTENTS TAB UP ABOVE----!!!][/rant]
    Ha, I didn’t even see the contents tab. Thank you, that’s a better way to organize it!

  2. Room descriptions:
    [rant]White Room is a room. [!!!----The description of the white room is ----!!!]“You are in a room that is entirely white. A heavy desk faces one wall. Beside the desk is a door.”[/rant]
    I thought I read somewhere that “The description of the room is” is optional if the description directly follows “X room is a room.” That’s why I left it out.

  3. Smelling while in a room:
    [rant]Instead of smelling while in the White Room, say “You smell paint fumes.”
    [!!!----- You dont need the “white room” part :slight_smile: -----!!!][/rant]
    So it’s not needed because it’s the only room in the game? I wonder if, in general, it is better to act as though you will have more than one room, in case you decide to add one later? I think my approach so far has been inconsistent with that.

  4. I was trying to account for the possibility of the player typing in “look room,” and my attempt didn’t work. James suggested doing it this way:
    [rant]Scen_room is a backdrop. It is everywhere. Understand “room/around” as Scen_room. [!!!----“It is everywhere” will work if your game has more than one room----!!!]
    Instead of examining Scen_room, try looking.[/rant]
    Thanks for this! That works a lot better! I also did not realize you could separate different items to “understand” with a slash. That’s good to know.

  5. For when the player types “help,” I had written
    [rant]After reading a command:
    If the player’s command matches “help”:[/rant]
    and James suggested saying “includes” instead of “matches” in case the player types more than just that word in the command line. Makes sense to me, although what if someone types “Ask Bob for help”? Maybe it is better to assume the player wants the help menu.

  6. For the part dealing with whether or not the player has heard the voice for the first time (and thus knows it exists), here’s what I had, and James’ comments:
    [rant]Heardvoice is a number that varies.
    Heardvoice is 0.
    The voice is scenery in the white room. The description of the voice is “[if heardvoice is 1]You can’t see the source of the voice.[otherwise]You can’t see any such thing.”
    Instead of touching the voice, say “[if heardvoice is 1]You can’t touch the voice.[otherwise]You can’t do any such thing.”.
    Understand “listen [something]” as listening to.
    After listening to the voice, say “[if heardvoice is 1]The woman’s voice has stopped speaking.[otherwise]You can’t hear any such thing.”

[!!!----I guess you are missing a “end if” at the end of your “if” rule :slight_smile: ----!!!]
[!!!---- Also, I so much prefer when you put periods out of the “if” rule, so that you have to print it only once and the linebreaking works better. Look here:

After listening to the voice, say “[if heardvoice is 1]The woman’s voice has stopped speaking[otherwise]You can’t hear any such thing[end if].”

----!!!][/rant]
I don’t know why I didn’t include “end if.”
I did notice that my line breaks didn’t work well at times, so hopefully putting the period where you said will take care of that.
Also, I wonder if it would be better to use a truth state or something else (instead of a number) to keep track of whether the player has heard the voice yet? Does it make a difference?

  1. Here’s what I had for singing. “Makenoise” is stuff that happens whenever the player does something that makes noise.
    [rant]The block singing rule is not listed in any rulebook.
    Understand “yodel” as singing.
    After singing, say “You sing loudly.[makenoise]”[/rant]

Here’s what James had:
[rant]Ouch, this is awkward. I don’t think you need the “block rule”. Just use an “Instead” rule in place of the “After”:]

Instead of singing, say “You sing loudly.[makenoise]”

[!!!----And I hope your “makenoise” ends with a full stop. Anyway, it is always better to leave punctuation out of say phrases.[/rant]
The “do not block singing” part may have come from an example I saw somewhere, but you are right that the game seems to work fine without it. I don’t exactly understand why “instead” works better than “after” here but I will read more about it.
Why it is better to leave punctuation out of “say” phrases? In this case, if I move the period or leave it out, the text is no longer punctuated correctly when you play the game.

  1. Here’s what I had for a new action, “conversing”:
    [rant]Conversing is an action applying to one topic.
    Instead of answering or asking or telling, try conversing.
    Understand “talk” or “talk [text]” or “talk to [text]” or “ask [text]” or “say [text]” or “speak” or “tell” or “tell [text]” or “yell” or “yell [text]” or “shout” or “shout [text]” or “scream” or “scream [text]” as conversing.
    After conversing:
    Say “[one of]‘Are you saying something, Charles?’ asks[if heardvoice is 0] a woman’s [otherwise] the [end if]voice. ‘I can’t hear you over my white noise machine.’[or]‘If you want to talk,’ says the voice, ‘why don’t you come in here where I can hear you?’[cycling]”;
    Now heardvoice is 1.[/rant]

James wrote:
[rant][!!!----Again, don’t use “after” when you need an “instead”. Your new actions (verbs), anyway, lack a Report rule:]

Report conversing:
if the player is in White Room: [!!!----Again, this is useful in games with more than one room----!!!]
say “[one of]‘Are you saying something, Charles?’ asks[if heardvoice is 0] a woman’s [otherwise] the [end if]voice. ‘I can’t hear you over my white noise machine.’[or]‘If you want to talk,’ says the voice, ‘why don’t you come in here where I can hear you?’[cycling]”;
now heardvoice is 1;
otherwise:
say “No one in the universe wants to hear you sing. Really.”.

[!!!----- CHECK THIS FOR THE SINGING VERB TOO-----!!!][/rant]
I will have to read more on this, I think, to understand when to use instead, when to use after, when to use report.

  1. James makes a good case for using the default response at times. I had written:
    [rant]Instead of putting something on the wall, say “You don’t have a way to attach anything to the wall.”[/rant]

James wrote:
[rant][!!!---- Is this needed? The default answer for trying to do something pointless is already built in Inform. It goes by the lines of: “Putting things on the wall would achieve nothing.”
As per convention, if a(n experienced) player sees such an answer (You don’t have etc.), he will try and find something to attach things on walls. If you DO NOT INTEND on having the player do such a thing, don’t tease him. ----!!!][/rant]
That’s a good point–I didn’t think of that!

I greatly appreciate all the work you put into this. I wasn’t expecting such extensive notes, so thank you so much.

I’ve asked some questions here in case anyone wants to clarify, but please, nobody feel obligated to spend more time on this unless you really want to…I am glad to have gotten even this much of a response.

Also, I’m not sure if the tabs worked correctly when I pasted the text. If not, sorry!

Thanks again!

That is true.

Why not make a new action instead of trying to work around the parser?

It doesn’t really make a difference but it is more elegant. If the person speaking appears as an object somewhere you could do “The woman can be heard or unheard”. That’ll read better and sound more natural.

The say phrase probably isn’t a good idea. Instead, you could do “singing is making noise” (and so on) and “instead of making noise”.
Inform 7 places line and paragraph breaks based on the punctuation at the end of your text, which in this case would be the end of [makenoise] rather than the end of the sentence.

In general you can trust the failure messages in the Standard Rules to be correct. Only replace them if they don’t fit your game.

You don’t need “The description of the white room is” unless you separate the description from the room declaration.

White Room is a room.  "This is a white room."

A room doesn’t get a description because usually people don’t “examine” a room. They “look”. (Not that this hasn’t been altered in some games.

I think James is getting slightly confused in that you can set an object’s initial description before giving it an actual description.

A rubber ball is in white room.  "Someone has discarded a rubber ball here, and it sits near one white corner."  The description is "It's rubber and bouncy and has a pungently rubber smell."

What you’ll see is

[code]White Room

This is a white room.

Someone has discarded a rubber ball here, and it sits near one white corner.[/code]

The rubber ball will use the “initial description” until it has been “handled”. I put these in quotes because you can test “If rubber ball is handled” to tell if the player has moved it, and specify “The initial description of foo is …” if you do it away from declaring the object. After the ball is handled (i.e., the player picks it up or moves it in some way" it will thenceforth describe in a paragraph as “You can see a rubber ball here.” if they drop it somewhere else.

That property of things is actually called “the initial appearance” rather than “the initial description,” so if you wanted to declare it away from the object you’d say “The initial appearance of foo is…”

Rooms do have descriptions. That’s why you can write “The description of the white room is…”

The bare string notation defines the description for a room, but the initial appearance for a thing. This can be confusing, so I explicitly write out “The description is…” or “The initial appearance is…” That’s just my habit though.

There are a few built-in rulebooks that we use for such things. These are consulted in turn, until a result of either Success or Failure is produced. Then the action-processing sequence stops. The order in which the rulebooks are consulted during each turn is:

  • Before
  • Instead*
  • Check
  • Carry Out
  • After*
  • Report

The asterisked rulebooks make a decision (default outcome is failure for the Instead rules, and success for the After rules). This means that if you introduce an Instead rule and that rule matches, that rule will automatically stop the execution of the rest of these rulebooks, and the action will have counted as never having happened.

In other words, it’s not meaningful to introduce an “after singing” rule when the “block singing rule” (which is a check rule; see below for the actual rule) already explicitly ends the action (“stop the action”), because your After rule will never be reached and thus never trigger. Similarly, adding a Report rule would not stop your After rule from firing, since your typical Report rule makes no decision.

Check an actor singing (this is the block singing rule): stop the action with library message singing action number 1.

The full turn sequence can be viewed here, but generally you don’t need to think about it in-depth.

Edit: made an error in the rules ordering, as pointed out by Draconis, which is now fixed.

Actually, I commented out “The description of White Room is” (which was not left out…) for two main reasons:

  1. nitpicking. It wasn’t necessary.
  2. “white room” was written lower caps and this could end in the room name being displayed incorrectly (I don’t know why or how, but I’m pretty sure it can happen).

Rooms have descriptions. In fact all rooms do, unless you want a room to display just the name. What they lack is an initial appearance because they can’t be placed around like objects.
The initial appearance of an object (or person etc) is the text that is printed when said object or person is not “handled” (as said above) or moved around. Like in:

[code]White Room
You are blah blah blah.

Sir Biss is hissing quietly in a corner.[/code]
The last line is the initial appearance, used instead of “You can also se Biss here.” which is particularly dull.

As for many of the other suggestions, they are all true and better than my use of Inform. Just let it be known that I was not rewriting the game from scratch :slight_smile:

Actually your own method is closer to what I have come to use nowadays. “Instead” is a bit too convinient in that it usually works for the specific thing you want to override, but becomes unwieldy in more complex actions. Generally the meaning of action rules is roughly:

  • Before: Things that always happen when the player tries the action (e.g. command clarifications)
  • Check: Conditions that block the action from happening and reporting unsuccessful attempts to the player
  • Carry out: Changes to the world model
  • Report: Reporting successful attempts to the player in the general case
  • After: Overriding report rules in special cases
  • Instead: Blocking the action and reporting it in special cases

Semantically I would write the action as:

[code]The block singing rule is not listed in any rulebook.

Report singing:
say “You sing loudly.[makenoise]”[/code]

This removes the check rule that blocks the action (the player doesn’t sing) and adds a report for successful action.

The extra bonus is that now the action has both been registered as successful by the engine and it goes through the normal action rulebook. Now, if you wanted, you could define all noise-making actions as “making noise” and move the [makenoise] part (which to me seems ok as it is) to an “After making noise” rule that would set the heardvoice flag. With an instead rule that wouldn’t be possible.

This will also include conditions that invoke implicit actions. For instance, the “can’t go through closed doors” rule in the standard rules (a check going rule) actually has the player try opening the closed door, and only stops the action if the door can’t be opened for some reason. (Which it checks simply by checking whether the door is open after the player has tried opening it.)

Well, you should be aware that “After” rules by default cut off the action when they run (that’s why they’re for special reporting cases), so if you want to run an “After” rule and still have your report rule run you need to include “continue the action” in the After rule.

If you were dealing with a specific action here, you could avoid this by setting the heardvoice flag in a Carry Out rule rather than an Instead rule. But you can’t use Carry Out with a kind of action, I don’t think. I checked my WIP where I have a flag that needs to be set by action of a certain kind and I do in fact use an After rule with “continue the action.” (I made it the first After rule so other After rules won’t block it.)

Sorry, James! I had been trying to decide whether to include it or not, and I guess I forgot what I finally chose. I misunderstood your brackets as an addition. My mistake.

To everyone,
I appreciate your help! Many thanks! :slight_smile:

Small correction: After comes before Report, so it can be used to override a Report rule (that’s why it usually succeeds).

Ack. Of course you’re right. I looked it up, misread, went “well, if that’s what it says” and went ahead to post the incorrect data. :slight_smile: