Discussions about interactive fiction

Archive for November, 2010

Inform 7 WIN32 IDE works fine for blind users

I’m a blind Inform 7 user and would like to point out that the current
WIN32 implementation works very well with my screen reading software.
It even seems this was considered in the design, as this usually
doesn’t happen by coincidence.

.
posted by admin in Uncategorized and have Comments (14)

Inform 7 – giving multiple names for one object

This is a pretty straightforward question, but I can’t find the answer
in the documentation:

If I have an object called Television, and I want the game to recognize
it by the name "television" AND by the name "tv," how do I go about
this?

posted by admin in Uncategorized and have Comments (3)

I7: Stymied at every turn

It seems every time I start trying to write something, some intractable
error crops up that I can’t figure out the solution to.

The last one was when the IDE decided to start adding smart quotes to
my source.  It took me a few minutes to figure that one out.  This
one’s really frustrating.  Namely, on my computer, this does not
compile:

"test8" by John Harris.

Default Room is a room.

Before printing the description of Default Room, say "Introductory
text."

The problem is:
Problem. You wrote ‘Before printing the description of Default Room’  ,
which seems to introduce a rule taking effect only if the action is
‘printing the description of Default Room’. The part after ‘when’ (or
‘while’) was fine, but the earlier words did not make sense as a
description of an action, so I am unable to place this rule into any
rulebook.

But the words "when" and "while" aren’t even anywhere in the source!
This code also won’t work a colon where the comma is.

Further, Graham Nelson’s "The Reliques of Tolti-Aph" won’t compile
either, due to the same error!  I’m thinking now, okay, this is really
weird.  Is it just my system?  I’ve sent off no fewer than six bug
reports, on various things, to Graham Nelson at this point, within a
week’s time, enough that I’m thinking I’m starting to seem a little
obnoxious.

I recognize this is beta software, and I’m trying to do my part with
the reports… but I don’t see anyone here mentioning this problem.  Am
I the only one having it?  Is the problem in my code after all?

- John H.

posted by admin in Uncategorized and have Comments (15)

Announcing: The Amazing Interactive Turing Machine

You have almost reached the end of your shift. All that remains is to
clean one final room, the control room for that weird contraption being
built by the scientists here.

Carrying your usual equipment, you open the door and step into…

The Amazing Interactive Turing Machine
An Interactive Waste of Time by J.D. Clemens

Currently available at:
http://www.math.psu.edu/clemens/IF/Turing
(and perhaps some day at the archive, but not now)

Written in Inform 7.
Not a game, so much as a proof of concept (which is why I’ve announced
it in both groups).
In fact, it’s not a game at all.

Enjoy,
-JDC

posted by admin in Uncategorized and have Comments (5)

Basic Action question in I7

I can say:

Instead of inserting somthing into the bin when the noun is not
the bauble, say "That fits only baubles."

I don’t find that syntax optimal. Can I say something like this
instead?

Instead of inserting anything but the bauble into the bin, say
"That fits only baubles."

or:

Instead of inserting something other than the bauble into the
bin, say "That fits only baubles."

The first other thing I thought of when my guesstimated syntax
didn’t initially work was a combination of two rules, one which
disallows inerting anything into the bin, and a more specific
rule that allows the bauble. But that doesn’t work, since the
more general rule can’t be skipped over.


Neil Cerutti

Inviato da X-Privat.Org – Registrazione gratuita http://www.x-privat.org/join.php

posted by admin in Uncategorized and have Comments (2)

I7 – Relations involving kinds/values

I’ve been trying to probe how Inform handles relations that involve
either kinds or values.

By way of illustration:

[-- begin code --]

"Gentlemen prefer Blondes" by Moynus Frey.

The plural of gentleman is gentlemen. A gentleman is a kind of man.

A blonde is a kind of woman. A brunette is a kind of woman.

Hair color is a kind of value. A person has hair color. The hair colors
are brown and golden. A person usually has the hair color brown.

Lorelei is a blonde. Lorelei has the hair color golden. Dorothy is a
brunette.

Sir Francis is a gentleman.

Shipboard is a room. Lorelei, Dorothy and Sir Francis are in Shipboard.

Preference relates various people to various people. The verb to prefer
(he prefers, they prefer, he preferred, he is preferred) implies the
preference relation.

[Test phrase]
Gentlemen prefer blondes.
[/End test phrase]

Every turn:
    repeat with potential love interest running through people
    begin;
        if Sir Francis prefers the potential love interest, say "Sir
Francis is smitten by [the potential love interest].";
    end repeat;

[-- end code --]

What I was hoping for, of course, was "Sir Francis is smitten by
Lorelei."

However, this produces the compiler error "You wrote ‘Gentlemen prefer
blondes’  : but something described only by its kind should not be
given a specific place or role in the world, to avoid ambiguity.   …"

Replacing the phrase with "All gentlemen prefer blondes." produces the
compiler error "You wrote ‘All gentlemen prefer blondes’  : but
complicated determiners are not allowed in assertions, so for instance
‘At most three people are in the Dining Room’ or ‘Most of the
containers are open’ will be rejected. Only simple numbers will be
allowed, as in examples like ‘Three people are in the Dining Room.’"

Replacing it with "Sir Francis prefers blondes." compiles, but it
startled me by producing: "Sir Francis is smitten by the blonde."
Looking through the index I find two instances of "blonde," Lorelei and
(nameless). Clicking on the orange arrow next to (nameless) jumps to
the line "Sir Francis prefers blondes." Apparently this assertion
created an instance of blonde? This has me really scratching my head.

Replacing our test phrase with "Sir Francis prefers women that are
blondes." and "Sir Francis prefers things that are blondes." has the
same exact effect. I was surprised that the last formulation, which has
Sir Francis preferring things, even compiled, when I specifically
defined the relation as "various people to various people".

Finally, when we replace the phrase with "Sir Francis prefers women
that have hair color golden.", we get the compiler error "In ‘Lorelei
has the hair color golden’   you give a value of the hair color
property as ‘golden’, but I can only suppose that must be the name of a
room or thing, since it does not seem to be a hair color – which this
property calls for." Sudddenly inform doesn’t recognize golden as a
hair color anymore.

Just for fun, I tried "Sir Francis prefers women that have hair color."
It compiles, but doesn’t do anyhing.

I’m surprised that none of these formulations have the intended effect.
Of course, I can only find reference to relations between actual game
objects (not involving kinds or values). Is there any way of getting
the effect I’m after in I7?

posted by admin in Uncategorized and have Comments (7)

[I7] Extension: Conditional Undo

So, let’s say you want to prevent undo from working *sometimes*, such
as after a certain random event, but not all the time. "Use undo
prevention" only lets you turn it off completely. Solution: this
extension!

Due to what I can only figure is a bug in the Inform library, you must
replace a routine in Inform7/Extensions/Reserved/Processing.i6 for this
extension to work properly with the current version of Inform. The
patched routine is included in a comment at the top of the extension.
On the plus side, the patch also fixes a couple built-in activities
like "deciding whether all includes something", which are broken in
3M43 because they rely on the same principle as this extension!

Version 1 of Conditional Undo by Jesse McGrew begins here.

"Allows fine-grained control over whether to allow commands to be
undone."

[–
IMPORTANT BETA NOTE:
  As of 3M43, the EndFollowRulebook routine in Processing.i6 must be
replaced for this extension to work. Here is the new code:

[ EndFollowRulebook  r;
  if (rulechange_stack–>rulechange_sp == RS_SUCCEEDS) r = 1;    ! JM
  else if (rulechange_stack–>rulechange_sp == RS_FAILS) r = 0;  ! JM
  else r = -1;                                                   ! JM
  rule_frames–;
  while (rulechange_sp > 0) {
      rulechange_sp = rulechange_sp – 3;
      if (rulechange_stack–>rulechange_sp == RS_FRAME) break;
  }
  if (rulechange_sp == 0) rule_frames = 0;
  if (r == 1) rulechange_stack–>rulechange_sp = RS_SUCCEEDS;    ! JM
  else if (r == 0) rulechange_stack–>rulechange_sp = RS_FAILS;  ! JM
!print "-<", rule_frames, "/", rulechange_sp, ">";
];

–]

Deciding whether to allow undo is an activity.

To allow undo: (- RulebookSucceeds(); rtrue; -).
To deny undo: (- RulebookFails(); rtrue; -).

The prevent undo flag is a number which varies.

To prevent undo: change the prevent undo flag to 1.
To do not prevent undo: change the prevent undo flag to 0.

To decide whether undo is prevented: if the prevent undo flag is 0,
decide no; decide yes.

Deciding whether the action prevents undo is an activity.

After reading a command (this is the reset the prevent undo flag rule):
        change the prevent undo flag to 0.

Every turn (this is the decide whether the action prevents undo rule):
        begin the deciding whether the action prevents undo activity;
        if handling the deciding whether the action prevents undo activity
        begin;
                do nothing;
        otherwise;
                if the rule succeeded, prevent undo;
                if the rule failed, do not prevent undo;
        end if;
        end the deciding whether the action prevents undo activity.

Include (-
Constant ALLOWUNDO_ACT = (+deciding whether to allow undo+);
Constant CANTUNDO_MSG = "That action cannot be undone.^^";

[ AllowUndo flag;
  BeginActivity(ALLOWUNDO_ACT);
  flag = ~~((+prevent undo flag+));
  say__p = 0;
  if (ForActivity(ALLOWUNDO_ACT))
    flag = RulebookSucceeded();
  if (flag == 0 && ~~say__p)
    print (string) CANTUNDO_MSG;
  EndActivity(ALLOWUNDO_ACT);
  return flag;
];
-)

Include (- Replace Keyboard; -) before the library.

Include (-
[ Keyboard  a_buffer a_table  nw i w w2 x1 x2;

    DisplayStatus();
    .FreshInput;

!  Save the start of the buffer, in case "oops" needs to restore it
!  to the previous time’s buffer

    for (i=0:i<64:i++) oops_workspace->i = a_buffer->i;

!  In case of an array entry corruption that shouldn’t happen, but
would be
!  disastrous if it did:

   a_buffer->0 = 120;
   a_table->0 = 15;  ! Allow to split input into this many words

!  Print the prompt, and read in the words and dictionary addresses

        #IFDEF NI_BUILD_COUNT; I7_Prompt(); #ENDIF;
        #IFNDEF NI_BUILD_COUNT; L__M(##Prompt); #ENDIF;
    AfterPrompt();
    #IFV5; DrawStatusLine(); #ENDIF;
    KeyboardPrimitive(a_buffer, a_table);
    nw=a_table->1;

!  If the line was blank, get a fresh line
    if (nw == 0)
    { i = etype; etype = BLANKLINE_PE;
      BeginActivity(PARSERERROR_ACT);
          if (ForActivity(PARSERERROR_ACT) == false)
L__M(##Miscellany,10);
          EndActivity(PARSERERROR_ACT);
      etype = i;
      jump FreshInput;
    }

!  Unless the opening word was "oops", return

    w=a_table–>1;
    if (w == OOPS1__WD or OOPS2__WD or OOPS3__WD) jump DoOops;

#IFV5;
!  Undo handling

    if ((w == UNDO1__WD or UNDO2__WD or UNDO3__WD) && (parse->1==1))
    {   if (turns==1)
        {   L__M(##Miscellany,11); jump FreshInput;
        }
#ifdef PREVENT_UNDO;
                print "The use of UNDO is forbidden in this game.^";
                jump FreshInput;
#endif;
        if (undo_flag==0)
        {   L__M(##Miscellany,6); jump FreshInput;
        }
        if (undo_flag==1) jump UndoFailed;
        if (just_undone==1)
        {   L__M(##Miscellany,12); jump FreshInput;
        }
        if (~~AllowUndo()) jump FreshInput;   ! JM
        @restore_undo i;
        if (i==0)
        {   .UndoFailed;
            L__M(##Miscellany,7);
        }
        jump FreshInput;
    }
    @save_undo i;
    just_undone=0;
    undo_flag=2;

#ifdef PREVENT_UNDO;
        undo_flag = 0;
#endif;

    if (i==-1) undo_flag=0;
    if (i==0) undo_flag=1;
    if (i==2)
    {   style bold;
        print (name) location, "^";
        style roman;
        L__M(##Miscellany,13);
        just_undone=1;
        jump FreshInput;
    }
#ENDIF;

    return nw;

    .DoOops;
    if (oops_from == 0)
    {   L__M(##Miscellany,14); jump FreshInput; }
    if (nw == 1)
    {   L__M(##Miscellany,15); jump FreshInput; }
    if (nw > 2)
    {   L__M(##Miscellany,16); jump FreshInput; }

!  So now we know: there was a previous mistake, and the player has
!  attempted to correct a single word of it.

    for (i=0:i<=120:i++) buffer2->i = a_buffer->i;
    x1 = a_table->9; ! Start of word following "oops"
    x2 = a_table->8; ! Length of word following "oops"

!  Repair the buffer to the text that was in it before the "oops"
!  was typed:

    for (i=0:i<64:i++) a_buffer->i = oops_workspace->i;
    Tokenise__(a_buffer,a_table);

!  Work out the position in the buffer of the word to be corrected:

    w = a_table->(4*oops_from + 1); ! Start of word to go
    w2 = a_table->(4*oops_from);    ! Length of word to go

!  Write spaces over the word to be corrected:

    for (i=0:i<w2:i++) a_buffer->(i+w) = ‘ ‘;

    if (w2 < x2)
    {   ! If the replacement is longer than the original, move up…

        for ( i=120:i>=w+x2:i– )
            a_buffer->i = a_buffer->(i-x2+w2);

        ! …increasing buffer size accordingly.

        a_buffer->1 = (a_buffer->1) + (x2-w2);
    }

!  Write the correction in:

    for (i=0:i<x2:i++) a_buffer->(i+w) = buffer2->(i+x1);

    Tokenise__(a_buffer,a_table);
    nw=a_table->1;

    return nw;
];
-)

Version 1 of Conditional Undo ends here.

—- DOCUMENTATION —-

This extension allows more control over the use of UNDO than the
standard "Use undo prevention" option. There are three stages where we
can intervene in the undo process, and each one can override the
previous one:

1. Use the phrase "prevent undo" in an action. This will prevent that
action from being undone. (If we change our minds during action
processing, we can say "do not prevent undo".)

        Instead of pushing the red button:
                say "You key in the launch sequence and fire off the nuclear
missiles. There’s no turning back now.";
                prevent undo.

2. Write a rule for the "deciding whether the action prevents undo"
activity. This activity runs at the end of each turn, and we can say
"it does" to prevent undoing the current action, or "it does not" to
allow undoing the current action (even if we said "prevent undo" in the
action itself).

        Rule for deciding whether the action prevents undo:
                if the player is wearing the time travel anklet, it does not;
                if the player was in the Zone of Permanence, it does.

3. Write a rule for the "deciding whether to allow undo" activity. This
activity runs when the player actually tries to undo. We can say "allow
undo" or "deny undo" to make the decision, and again, the decision we
make here will override any decision made in stage 1 or 2.

        Rule for deciding whether to allow undo:
                if the turn count is greater than 5
                begin;
                        say "Too late for that, buddy.";
                        deny undo;
                end if.

Notice that we printed our own denial message in the above example. The
"deciding whether to allow undo" activity is the only place we can do
that; if we don’t print a message, or if we prevent undo from stage 1
or 2, the player will normally see the default message ("That action
cannot be undone"). However, we can write a rule for this activity that
detects whether one of the earlier stages has already prevented undo,
and prints a custom message if so:

        After attacking someone (called Todd):
                say "[The Todd] will never let you live that down, bro.";
                prevent undo.

        Rule for deciding whether to allow undo:
                if undo is prevented, say "You’ll just have to deal with the wrath of
your enemies."

IMPORTANT BETA NOTE

As of Inform 7 beta build 3M43, a bug in the library makes it difficult
to know whether an activity has succeeded or failed, but this extension
needs to know. For now, we can work around it by modifying the
EndFollowRulebook routine in the file "Processing.i6" (part of the
Inform distribution in Inform7/Extensions/Reserved). The replacement
code is included in a comment at the top of this extension; the only
change is that the five lines marked with "! JM" are added.

posted by admin in Uncategorized and have Comment (1)

Would you like to RESTART, RESTORE a saved game or QUIT?

Just wondering, can this message:

Would you like to RESTART, RESTORE a saved game or QUIT?

…that appears when a game is lost, be altered?  I’d like to put the
UNDO in there beginning gamers, who don’t realize it’s an option.

Thanks!
B

posted by admin in Uncategorized and have Comments (4)

Code for robust secret doors and secret switches

Just for puzzler, here’s a copy of the code in the extension I’ve
forwarded to Graham:

A secret door is a kind of door.
A secret door can be revealed or unrevealed.
A secret door is unrevealed.
A secret door is scenery.
A secret door is closed.

A secret switch is a kind of thing.
A secret switch can be revealed or unrevealed.
A secret switch is unrevealed.
A secret switch is scenery.

To print the you can’t go message:
        (- L__M(##Go, 2, 0); -).

To print the you can’t see message:
        (- L__M(##Miscellany, 30, 0); -).

Before going through a secret door which is unrevealed:
        print the you can’t go message instead.

Before doing something to a secret door which is unrevealed:
        print the you can’t see message instead.

Before doing something when when a secret door is the second noun and
the
second noun is unrevealed:
        print the you can’t see message instead.

Before doing something to a secret switch which is unrevealed:
        print the you can’t see message instead.

Before doing something when when a secret switch is the second noun and
the
second noun is unrevealed:
        print the you can’t see message instead.

posted by admin in Uncategorized and have No Comments

Celtx screenwriting software

This may be of interest to anyone writing IF with a large number of
characters and/or scenes.

Celtx is a free tool for creating screenplays. Versions for Mac,
Windows and Linux are available in various languages from:

http://www.celtx.com/download.html

I originally discovered it while looking for a screenwriting tool, but
I find its character and scene management tools are equally helpful
when writing large scale IF, and it may even lead to better writing.

posted by admin in Uncategorized and have Comment (1)