Hi Jim, good catch! Sorry for that; I was happy to find a (sort of) solution for the immediate issue when the door is locked, but simply didn’t think to test the case when it’s not locked.
The behaviour you describe (that neither the player nor the pushed/pulled object actually travel after having done the implicit door-opening) also happens in unmodified adv3Lite, without my suggestion above in this thread.
I used the debugger and breakpoints to trace the execution, and I think I know what’s causing this, but I don’t know enough about TADS and adv3Lite to suggest a good solution.
When we’re attempting to push/pull the object through the door, we’re landing, after quite a long chain of function calls, in the function check(obj, checkProp)
(defined in action.t
), with obj
at that moment being the door and checkProp
being checkIobjPushTravelThrough
. Inside of that function, we encounter this:
/* Run the check method on the object and capture its output */
try
{
checkMsg = gOutStream.captureOutputIgnoreExit({: obj.(checkProp)});
}
In the course of running that check method on the object, TADS will see that the door is closed, and will open it implicitly. In adv3Lite without my modification above, this will result in the pushed object opening the door. With my modification, it will result in the player character opening the door.
Since this is just a sort of “test run”, the output is not displayed yet, but captured, just as the code comment says.
The output will either be something like “The trolley opens the lab door.
” if it was the pushed object which opened the door, or the classic “(first opening the lab door)
” if it was the player character. In any case, the output will not be empty in this constellation, and consequently checkMsg
will not be empty.
Now comes the crucial part: Further down in the check(obj, checkProp)
function, we arrive at
/*
* If the check method tried to display something then it wants to
* block the action, so we display the failure message and stop the
* action.
*/
if(checkMsg not in (nil, ''))
{
[...]
/* Display our failure message */
say(checkMsg);
/* Note that the action failed. */
actionFailed = true;
/*
* Return nil to tell our caller this action failed the check
* stage
*/
return nil;
}
So the output that was built by obj.(checkProp)
and assigned to checkMsg
earlier, in the line checkMsg = gOutStream.captureOutputIgnoreExit({: obj.(checkProp)});
, will now make TADS think that the action failed and should be blocked.
And so the innocuous information that’s stored in checkMsg
(“The trolley opens the lab door.
” or “(first opening the lab door)
”) is now considered to be a failure message. The interpreter then displays the message, and the rest of the action is not executed; that is why neither the player character nor the pushed object actually travel.
One can verify that the problem lies in the output during that check phase by turning off implicit actions reporting like this:
modify Open
reportImplicitActions = nil
;
and also inserting the modification from above on our door object
checkPushTravel()
{
checkTravelBarriers(gActor);
}
because otherwise “The trolley opens the door.
” (resulting from the trolley’s visible door-opening) will be counted as check phase output, causing the action to be considered a failure.
So, with both of those modifications in place, the player and the pushed object will actually travel (after opening the closed-but-not-locked door without a message being displayed):
>push trolley w
You push the trolley through the lab door.
Lab 2
The trolley comes to a halt.
But of course, this is just for testing, and is not a good solution in general, because we want to keep the implicit action reports.
It seems like a bug for Eric to look into, or maybe other adv3Lite users can help.