curiousdannii-testing / inform7-imported-bugs

0 stars 0 forks source link

[I7-2015] [Mantis 2052] Inform library calls "after" rule when a container is inserted in an unopened container #69

Closed curiousdannii-testing closed 2 years ago

curiousdannii-testing commented 2 years ago

Reported by : turthalion

Description :

Given the following code snippet:
Object -> plain_bag "plain shopping bag"
with name 'plain' 'shopping' 'bag',
description "A plain shopping bag that can hold 2 things.",
capacity 2,
has ~open openable container;

Object -> jar "jar"
with name 'jar',
description "A jar.",
capacity 2,
after [;
Open: print "You twist off the lid of the jar";
if (children(self) == 0)
". The jar is empty.";
print ", revealing ";
WriteListFrom(child(self), ENGLISH_BIT);
print_ret ".";
],
has ~open openable container;

Object -> -> jam "jam"
with name 'jam',
article "some",
description "Some jam.",
has edible;

... the following output is produced:
Kitchen
This is a large country-style kitchen.

You can see a plain shopping bag (which is closed) and a jar (which is closed) here.

>open jar
You twist off the lid of the jar, revealing some jam.

>close jar
You close the jar.

>put jar in bag
(first taking the jar)
(first opening the plain shopping bag)
You twist off the lid of the jar, revealing some jam.
You put the jar into the plain shopping bag.

>x jar
A jar.

>l

Kitchen
This is a large country-style kitchen.

You can see a plain shopping bag (in which is a jar (which is closed)) here.

>

When the jar was put in the shopping bag, the shopping bag needed to be opened, but the after rule for the jar was printed. As seen by looking afterwards, the jar did NOT open, but its after rule was run.

Steps to reproduce :


Additional information :

imported from: [Mantis 2052] Inform library calls "after" rule when a container is inserted in an unopened container
  • status: Closed
  • resolution: Resolved
  • resolved: 2022-04-07T05:02:33+10:00
  • imported: 2022/01/10
curiousdannii-testing commented 2 years ago

557058:4c095ffd-6d6f-47ce-9e73-77c613347b86:

Comment by DavidG :
Also reported at https://github.com/DavidGriffith/inform6lib/issues/52

curiousdannii-testing commented 2 years ago

557058:4c095ffd-6d6f-47ce-9e73-77c613347b86:

Comment by DavidG :
Fix applied in https://github.com/DavidGriffith/inform6lib/pull/53

curiousdannii-testing commented 2 years ago

557058:4c095ffd-6d6f-47ce-9e73-77c613347b86:

Comment by jpavel :
Looking at this message trace

> put jar in bag
[Moving jar to yourself]
(first taking the jar)
[ "country style kitchen".before() ]
[ "jar".before() ]
[ "plain shopping bag".before() ]
[ "country style kitchen".before() ]
[ "plain shopping bag".before() ]
[Giving plain shopping bag open]
(first opening the plain shopping bag)
[ "country style kitchen".after() ]
[ "jar".after() ]
You twist off the lid of the jar, revealing some jam.
[Moving jar to plain shopping bag]
[ "country style kitchen".after() ]
[ "jar".after() ]
[ "plain shopping bag".after() ]
You put the jar into the plain shopping bag.

We see that ImplicitOpen is calling after() on the wrong object (jar rather than bag).

ImplicitOpen calls AfterRoutines() after performing the action, but we see in AfterRoutines

if (inp1 > 1 && RunRoutines(inp1, after)) rtrue;

that it checks inp1, which in this case is the jar, and runs its after routine.

I've only just begun looking at the library, so how to fix this safely, I don't know.

~Jesse

curiousdannii-testing commented 2 years ago

557058:4c095ffd-6d6f-47ce-9e73-77c613347b86:

Comment by jpavel :
I've tried replacing ImplicitOpen so that it sets inp1 to obj before calling AfterRoutines(), and it seems to work...

(see code below)

Jesse
--------------
Replace ImplicitOpen; ! Before Include "VerbLib"

! ==========================
! and later on in your story

[ ImplicitOpen obj
res temp temp2;
if (obj has open) rfalse;
res = CheckImplicitAction(##Open, obj);
! 0 = Open object, Tell the user (normal default)
! 1 = Open object, don't Tell
! 2 = don't Take object continue (default with no_implicit_actions)
! 3 = don't Take object, don't continue
if (res >= 2) rtrue;
if (obj has locked) rtrue;
temp = keep_silent; keep_silent = 2; ; keep_silent = temp;
if (obj hasnt open) rtrue;
if (res == 0 && ~~keep_silent) L__M(##Open, 6, obj);
temp = action; action = ##Open;
temp2 = inp1; inp1 = obj;
AfterRoutines();
inp1 = temp2;
action = temp;
rfalse;
];