I6 version of Object Response Tests?

Hi, I was wondering whether there was anything in I6 that would work similarly to the I7 extension “Object Response Tests”. I really like that extension.

I could, of course, try to make one myself, quick and dirty, for private use (being that I’m not a programmer, per se, but when the mood strikes me I won’t rest until I’ve cobbled together something minimally functional for my needs), but I figured I’d ask to see whether there’s already a wheel before I reinvent it.

I look at Inform - Resources - Extensions , naturally, but there doesn’t seem to be one there.

In the brief period of time I was actually trying to get something done in I7, I remember this extension coming out and finding it perfectly suited to my needs. Now that I’m playing around with I6 and implementing “Ruins”, and trying to resolve some of the exercises in DM4, and in some cases adding some objects/responses myself if I feel they are warranted, I really miss that extension; seeing action responses live and in game can feel very different from just coding them into my text editor, and that’s when stuff goes as planned. Which, naturally, is only a fraction of the time.

Again, trying to make something like this could be an interesting exercise for myself, but I wanted to see whether someone else had already done it.

As not-unexpected, I’m having some fun making it myself.

I don’t expect there’d be interest in it, would there? If there had, someone with proper skills would have made it already, I’m just cobbling something together. If there’s interest I can share, but otherwise I’ll probably prefer not to embarass myself by showing it when it’s done. But, again, if there’s interest, I can take the embarassment. The idea is that you can type >ORT to run through all verbs that don’t take nouns, and >ORT (noun) to run through all the verbs that apply to a single noun, with a few dummy containers and supporters being brought into the location when applicable to test appropriate behaviour… So it’s simple, and I’m sure it’ll break horribly easily, but I’m having fun trying to keep it together. Doesn’t look like it’d be hard to add new verbs to it, either.

…can this sort of thing be used in PunyInform, or something? Since there seems to be a renaissance going on?

PS, memo to self so I don’t forget, I also want to make sure that certain verbs are not automatically called by ORT on some nouns if they might change the game state and be a hindrance rather than a help. I’m making this note for myself because I’d actually forgotten about this, so I’m reminding myself.

Not sure how the extension knows which actions exist, which actions take a noun, and which actions take two nouns. If it’s just a matter of the programmer listing the actions, I would expect the extension to work with PunyInform without any modification.

1 Like

Yeah, just as in the I7 extension the programmer has to extend an existing table, in what I’m doing the programmer does have to add each action individually where appropriate.

It would have been much simpler if I could do a “do an action, undo, do the next action” to avoid the game state being changed, like in Hypothetical Object Response Tests? but in I6, but since that is beyond my ken - and I’ve tried, but I’m just not at that comprehension level, even if I could figure out how to save the gamestate; write a variable into an external file; perform an action on a switch dictated by that variable; increase the variable on that file by one; restore the gamestate; reread the variable, which is now up by one and should trigger the next action in my switch; continue like this… Even if I could put this into practice, which I failed at, I think the game will still stop executing the code after a successful restore, so the rest won’t get called - I’m giving properties to objects to mark them for “not ORTing”. I imagine this will bloat unnecessarily, and it makes the actual ORT code, which should otherwise have been simple to add to, more cumbersome. Bloat would be obviously very unwanted in PunyInform since, I as I understand it, the whole point is to make it as lean as possible; and “cumbersome to use” is just a bad thing.

I look at it, sigh, and think “well, as usual, this is something that I will find extremely useful for myself but can’t in good conscience foist on anyone else for its bulkiness and roughness.”

Would otherwise have loved to contribute in some small way to the community. But then again, as I mentioned, if the community actually needed/wanted something like this, someone would have made it. So I’ll just wrap the code around an “#ifdef debug”, accept that the properties on the objects are not going to go away when I remove the -d switch, and use those properties sparingly anyway. It’ll be useful to me if no one else.

True, but as long as it doesn’t bloat the released game, it’s fine.

If one needs to add properties to many objects just for this, that would probably add bloat even in the release version though.

As for undoing every move - you could perform an undo at the end of an ORT run - that would put the game back in the state it was before the run.

2 Likes

Hmmmm. As opposed to undo after each single step? For instance, if I ORT a key, and the output is like,

>examine the key

“It is a key.”

>search the key

You find nothing of interest.

>take the key

You pick it up and it melts into thin air! A mirage!

…at which point the key gets removed, the remaining actions in that list won’t be able to do antyhing with the key any more. So I was trying to PerformUndo after each single step. Examine, undo. Search, undo. Take, undo. If I undo at the end of the ORT run, if I don’t misunderstand, it would not address this case, would it?

Yeah, I can bypass all of it by putting it in DEBUG thing. That satisfies me; no bloat. But the properties… that bloats, and I don’t like that. :confused: It’ll have to stay unless I can find an alternative. I thought maybe it’d be best to have just one property which contained a string like “.examine.search.take.” and then match whether the property contains, like, “.search.” and if so skip searching… but I since found out that I6 doesn’t really have string manipulation that I can use, not at my low level… I think maybe that would at least be better because it would be just a single property, but even if it is less bloat, it’s still unnecessary bloat (for release).

No, a single undo at the end wouldn’t address this.

Could you just move all the objects required for an action into place before every action is performed? Of course flags may have been set or cleared, timers may have been started etc, so they may be in a different state than before.

A perfect solution will be hard or impossible to achieve.

1 Like

I can try that, I guess… I’m not super keen because I have a feeling that an unexpected situation will come and bite me in the derrière later.

Yeah, the perfect solution would be the equivalent of the player typing x key ; undo ; search key ; undo; take key ; undo ; etc. If I could get that behaviour…

…’cause everything else, the actual running the actions, is pretty trivial. If I didn’t care about this game state thing, it’d just be busywork. But I think it’d be important to care about it, and if I don’t, then I really can’t think about it being properly useful in diverse cases.

BTW, I really appreciate your time and expertise. :folded_hands:

There are extensions for string manipulation, or you can code it yourself. However, the relative lack of functions for string manipulation in Inform 6 is mainly a problem for people new to Inform 6 - most of the time, there’s really no need for it.

As for what you mention here, it sounds like you want to exclude certain actions for certain objects, and that’s better done by referring to their action numbers. E.g.

Object Paper "paper"
  with 
    name 'paper',
#Ifdef DEBUG;
    exclude_actions ##Examine ##Search ##Take,
#Endif;
  has light;

This avoids unpacking a string, matching its contents character by character to the name of each action etc.

2 Likes

That looks juicy and delectable! However, I don’t want to exclude them entirely; I want to exclude them when ORTing. Would that be possible? For instance, I want the player to be able to take the key, but I want ORT to ignore that action for that object.

I appreciate that, because I don’t want to make I6 fit my mindset; I want my mindset to fit I6, to make the best of it. In I7, I would think nothing of matching text. I6 is less carefree. I am finding that invigorating.

exclude_actions is just a new property I made up. No part of the code will care about it, except where one adds support for it. So, you could make your ORT extension check for this property on each object, and adapt. Maybe rename the property to ort_exclude_actions to make it clearaer what the property is for.

1 Like

I see! I’ll have to look into it. Better than the multiple properties thing for bloat. Thanks! (I was currently giving them properties like DontListen, DontTake, etc, and then checking in my Ort sub whether the noun had the property; if so, print text saying we’re skipping it; if not, do the action; and doing this line by line, action by action, manually. Pretty cumbersome for a user to add a verb to, when they add their custom verbs)

I had a thought. This thought came to me while I was thinking, step by step, how messages get sent to objects in I6.

I tested this thought.

It seems to work, but I may yet trip somewhere. Right now I’m a bit too happy that it works to be objective.

#ifdef DEBUG;
Global ORTing=false;

[OrtOneNounSub;
   ORTing=true;
   (…)
   style bold; print "> take ", (the) noun ,"^"; style roman; <Take noun>;
   (…)
   ORTing=false;
];
#endif

(when declaring the object KEY)
before [;
   take:
         #IfDef DEBUG; if (ORTing==1) “ORT blocked!”; #endif;
     remove noun;
      “The key vanishes!”;
];

This… seems to work! OrtOneNoun sets the global variable to 1, to indicate that ORTing is happening; it sends to the noun the message that it should trigger the action “take”; if the noun has a “before” rule that explicitly says “nope, not while ORTing == 1”, the action is blocked; otherwise, continue. What the developer would have to do, then, would be to add that “#ifdef” line for every action that they don’t want ORTd; and since for the most part they’ll be things that change the game state, chances are excellent there is already some sort of “before” in there already in which to just paste this.

I’ll see how this develops. It pleases me.

EDIT - The above already showed me that, in a practically empty environment of only one key, one table (supporter) and in one room with light, “implicitly taking” the key (as in, “put key on table”) does not trigger the “ORT block taking” line. But I will chalk this down to my own inexperience, and will continue learning I6 properly once I’ve got this basic framework down, because I want to use all of this as I continue to learn. I’m sure there’s something I missed that made this happen.

So my point is: it already pointed something unexpected to me. Which is exactly what I want it to do! Ooooh, I feel all warm and fuzzy inside.

EDIT 2 - Also, if I have a bag that is big enough for the player to go in, and I enter the bag, and then I try to take the bag, it says “You’ll have to get out of the bag first.”; but if instead I do “drop bag”, while IN the bag, I get an error:

(first taking the bag out of the Test Room)

[** Programming error: tried to “move” bag to bag, which would make a loop: bag in bag **]

This with an extremely simple bag, which just “has container open enterable”.

So yes. This is being useful already.

I don’t know for sure if this will help you or not, but I believe we recently established that Inform 6 has ‘record’ and ‘replay’ verbs that are on by default (they were debugging verbs in I5). And you can put undo’s in those recorded commands. I think.

So one option might be to create a test_everything.rec file, pepper it with undo’s, and run it with ‘replay’?

2 Likes

Definitely a possibility to look into, although I can’t yet quite visualize how I could make the commands work for each item - I can currently “ort”, “ort camera”, “ort trees”, etc quite easily. Using the record and replay I may have to edit the file every time to replace the noun of what I want to test. I actually consider the “undo” thing resolved as of my last post, that solution involves only a global variable and is easy to implement - UNDO was only ever a way to avoid changing the game state in the middle of ORTing, but now that I can easily block those action from being ORTd in any instance I desire, I’m satisfied. It is simple enough to test, quit, add a line to block an ORTd action, recompile and test again. I don’t see this as a tool that is heavily used all the time anyway; a couple of times for each object, first early in development to give ideas how to mange the responses and then later when a certain section or location is as good as completed, just to make sure. This piece of code is kinda meant to reveal stuff that you go tinker with immediately, it’s not really something that has to be resilient enough to endure a lengthy playthrough.

When trying to implement ORT for the verbs which require topics, like consult and ask, I ran into the limit of what I can do at this exact point, so now I’m unhurriedly pausing ORT to continue reading through the DM4 until I get to that relevant chapter.

In the meantime, it’s already proven to be a useful tool to me, in the sense that I can look at a certain interaction result for a certain command and ask myself “is this a desirable output” and continue from there.

There are possibly many verbs that may be considered superfluous to test on everything every single time, lile swing and switchoff and pray, but since the point is to catch unexpected situations, it makes sense to cover all bases.

I’m currently least satisfied with how a user can implement their own verbs. Right now I can only envision that they have to open the .h file, go to the sub, and in the end of the sub there’s an area clearly marked where they can add new verbs, following the template of all the others. I don’t like that a user has to open the extension file directly and edit a copy of it for every game. If that’s the case I may instead recommend the code is simply copy-pasted into the project, and not kept separate.

Anyway, so it’s currently paused while I learn more I6, but it’s only those actions that are missing. In the meantime I’m actively using what I already have as I continue to experiment with examples and exercises in DM4. It’s practically finished for its intended use.

Interestingly I have found that, if during ORT I pick up an object which has a custom “after take” reply (namely the mushroom in Ruins) which checks to see whether it ‘has moved’… well, later on down the line, the mushroom is dropped during ORT as well, and if I try to pick it up again I still get the custom text which shouldn’t appear anymore. I figure that there is code to update that which only gets called at the end of all the actions, and since ORT takes and drops within a single Sub, by the end the game may check to see whether it is still where it was… and it is, because it was dropped after being picked up… so it doesn’t give it “moved”.

I am actually not very interested in ensuring that situations like the above work better because it’s outside the scope of what I intend to use this for: to quickly check responses and ensure that I find the results are desirable (and if not, add a few rules, maybe an object or two to capture an interaction which I think is too sensible not to be better recognised).

ORT has also shown to me some iffyness in implicit actions as they work by default, so I’ll need to take care. I have an action that blocks an item from being taken, but it’s implicitly taken anyway if I try to put it into another item! That’s the sort of behaviour I hope ORT helps catch, too.

Not to mention the bag thing I mentioned earlier. That’s default behaviour I’m getting, just by implementing a regular object in a regular room. So if I want to implement a sleeping bag, I need to ensure that I model properly blocking it from being implicitly taken when the player is in it, since the default world model doesn’t and results in that error.

Yep, if I know that certain implicit actions should just be removed - if I want to block implicit “taking” when “dropping” - I can resolve that by working on that level. But I still needed the behaviour to be exposed, so that I knew there was something to correct. And this is where I think ORT is useful, potentially.

To clarify: after these issues appear, I try to reproduce them manually, without ORT. And they are reproducible. So it’s not ORT screwing up.

EDIT - It’s also revealing to me that I can “drop west” to get the result “(first taking the west out of the compass) Dropped.” I’ll be honest, I expected the standard world model to be a little bit sturdier than this out of the box. But no matter! Because of ORT, I am exposing issues that need to be fixed! Because, without ORT, my code for a room where everything you drop goes to a different room - together with this implicit “take” on dropping - meant that I could drop “the west”, and have it go to a different room, and then I couldn’t move anymore! And I probably wouldn’t have though of anything to trigger this situation without the ORT.