adv3Lite version 1.6 release imminent

I’ve recently gone back to working on adv3Lite (recent retirement has given me a bit more time for such things) and I’m hoping to release adv3Lite version 1.6 fairly soon. I’m currently going back over the posts in this forum to see if there are any issues I need to address, but if anyone has any other suggestions or has encountered any bugs that need fixing, this would be a good opportunity to let me know (e.g., by replying to this post).

14 Likes

Hi Eric! I had worked up a pretty handy system in my own game for defining super-simple verb responses (based on macros). The system doesn’t interfere with or replace any default library behavior. I had started doing a port of the code from adv3 to adv3Lite, but I haven’t had a lot of extra time for such fun projects, and I haven’t ever learned how to use Lite yet (I’m still on my first game, three and a half years later…).
I’ll just make a small pitch, solely for your consideration! It’s something you could easily bundle in as a standalone file if it seemed worthwhile.
The point of the system is to provide a very terse way to incorporate more action responses into a person’s game, without having to wrap every little one-liner in a big dobjFor block. It can be applied to library verbs and custom verbs alike. It is not intended to replace the use of dobjFor for any kind of actions that pass verify() sometimes, and sometimes do not.
The system is based on a prefix plus the root Action name. The prefix n- means “not/can’t”, and the prefix k- means “okay/we’re proceeding”. (The prefixes themselves could be changed too, but they seemed to the point to me, along the lines of gActor and tTopic…)
Code may look like the following:

object: Thing 'vocab' "desc "
    nOpen = 'Witty one-liner here. '
    nEat = 'Don\'t do that or you\'ll die. '
    kJumpOver = 'You wow the onlookers with a spry leap clear over the object. '
    kBlowOn = '<<if !beenCleaned>>Dust goes everywhere. <<else>>Nothing really happens. '
    nGoThrough = 'It should be obvious you won\'t fit through the object. '
    kClean { if(beenCleaned) failCheck('It doesn\'t need any more cleaning. ');
        "Using some spit and a sleeve, you give the object a shine. ";
        beenCleaned = true; }
    dobjFor(Turn) { verify { /* something conditional happens here so we use
                        the traditional approach */ } 
           action { ... } }
    cannotReadMsg = 'We can still use the existing properties too.'
   // etc...

The thing that sets the system apart from being just a bunch of abbreviations, is that if you use the n- prefix, the action will fail in verify. Whereas if you use the k- prefix, the action will unconditionally clear verify, and listed preconditions will be applied. So you don’t have to worry about your messages being printed in incongruous situations, like where you shouldn’t be able to touch the object without an implicit action.
And while you are able to define them as simply as a string, you can also use method brackets if you need to use multiple code statements.
Okay, I’ll be done! I can give you much more info if you think it’s something you want to look into, or otherwise it could potentially work as an extension too.
Thanks again for your work, Eric! Your docs are what brought me into the TADS world… Congrats on retirement!

3 Likes

I appreciate you!! adv3Lite is what got me into authoring IF!

I might have found a bug before, but it was after I added a lot of custom functionality so lemme write a quick default test case and get back to you…!

EDIT: Also!! Congrats on achieving retirement!! You’ve certainly earned some rest!

EDIT 2: There was no bug; there seemed to be something I changed in the Room implementation that somehow caused it, so that one’s on me! I was getting crashes from trying to FEEL a room, but I’ll have to see what I did lol.

2 Likes

Thanks both.

John, your “pretty handy system” looks interesting, and may well be a good candidate for an adv3Lite extension – or maybe part of the main library (depending on the implementation), so I’d certainly be interested in seeing more info about it. (My main reason for thinking it may be better as an extension, at least initially, is to avoid confusing users with too many ways of achieving similar things in the core library, which won’t be a problem if it’s presented as an extension).

Joey, I looked through some of the posts in this section earlier today and recall seeing one about a FEEL ROOM bug, I wasn’t able to reproduce this problem when I tried it earlier today, but neither can I find anything in the 1.6 change log that explicitly addresses it, which may mean (1) it was fixed as an incidental side-effect of fixing something else (which doesn’t seem all that likely, but may not be impossible or (2) that I did explicitly address it some time back but forgot to include it in the change log or (3) that something really odd is going on!

3 Likes

With the caveat that I’m not a real coder … I think one way of doing this in an extension would be to define a new flag value (hasMessages) in the Thing class. If hasMessages is true, then when the library gets ready to consult, let’s say, dobjFor(Eat) it looks to see if there’s an nEat or kEat on the object. If not, the normal action handling takes place.

You could also do this by redefining Thing in the library so that each dobjFor() can use nEat or kEat if hasMessages is true, or use the default messaging system if hasMessages s nil. There may be other ways to do it.

The nice thing about the BMsg system is that it allows the use of parameter substitutions. Building that into this proposed messaging system would just complicate matters. I see, for instance, that your line for kJumpOver has the output text “over the object.” That’s a case where one might need some parameter substitution in the library. An individual object that defined kJumpOver wouldn’t need it – just use the object’s name in the text.

The thing about substituting these handy text widgets for the output from check() is that I often want to use an if-test within the check() block. So I might not want to use this new system for one action on an object, but I might want to use it on a different action in the same object. Having the library sort all that out might get a bit hairy.

1 Like

Hey Jim… without yet being a Lite user, I don’t know if I understand all of your concerns at first. Let me just try to say a few things and you can tell me if there are still problems.
Let’s say you include files we’ll call nkSys.t and nkHeader.h in your t3make file. As far as I can tell, you don’t need to set a hasMessages flag… you can freely mix k’s and n’s with dobjFors in the same object, or never use k’s and n’s at all. If you use a k- or n-[Verb] property, the system will use that accordingly, just for that individual Action/Thing combination. All other actions for that object are unaffected. If you don’t define nEat, all the usual isEatable/cannotEatMsg/inherited dobjFor(Eat) block is in play. So you can use nEat, kJumpOver, and then still use dobjFor(Something) with a check() block, without having to worry about whether this object has a hasMessages flag or not.
Also not mentioned in this thread yet, the system also has a ch- prefix for actions that you specifically want to nix in check() phase as opposed to verify. Any actions that pass check sometimes and sometimes not should be coded in the traditional way: the system isn’t trying to replace that approach. It’s geared for straightforward responses (although you are still able to do some conditionals like this:)

kEat { if(isPoisoned) failCheck/[Lite equivalent]('Better not. ');
    else { "You eat some x out of the y, but there's still a lot left. "; } }

Furthermore, I don’t see any reason why you couldn’t use BMsg in kJumpOver (or any other n-/k- message). I just scribbled a hasty example from an adv3 background. You can do You jump over <<gDobj.theName>>. or {You/he} jump{s} etc. or kJumpOver = BMsg(...), (at least, I merely assume that the BMsg returns a string?) At least in adv3, it’s important that nVerb messages are defined as (or return) strings, because they are passed to the illogical macro… if Lite is the same in this respect, then that’s still important. kVerb messages can be defined as strings, DQstrings, or methods.

This is fantastic to hear! As I mentioned to @Jim_Aikin elsewhere, I noticed that both our IF Comp 2022 entries are in adv3Lite, which is a nice testament to its power and usability. It’s good to know work continues on the library.

Are you working on the library out of a public repository, such as GitHub? I ask because I have a number of fixes I’d like to propose for inclusion. I’d prefer to offer them to you as patches or pull requests than copy-and-pasting them here.

Even if you don’t accept my changes directly, that would be an easy way (for me, at least) to alert you to the problem and give you at least one proposed solution.

Also, are there any new features in 1.6 you could preview for us?

2 Likes

It’s at GitHub - EricEve/adv3lite: Source code and documentation for adv3Lite, an alternative library for use with TADS 3. I don’t think the current (unreleased) version is there yet.

2 Likes

I did see that, but it hasn’t been touched since 2017. I wasn’t sure if that’s the official/working repo for adv3Lite.

You may be right. Looks like the current version is at Dropbox - adv3Lite15.zip - Simplify your life

1 Like

Eric, is it intentional that iobjFor(UnlockWith) has no preconditions, unless it’s a Key?

I haven’t been using that repo recently, so don’t rely on it to hold the latest working version. At some point I’ll probably need to revive it, but it’s been such a while since I used it, I’m feeling a bit rusty on Git just now, and my current working director for adv3Lite is not the one linked to the GitHub repo.

2 Likes

This also applies to iobjFor(LockWith). I’m guessing my original thinking was not to use the objHeld precondition in each case since, if the object is not a key, it would seem a bit klunky to perform an implicit take on the iobj only to have the game say you can’t unlock anything with the iobj. But there probably should be some precondition here, so I’ve now added touchObj (on Thing) instead.

1 Like

It’s mostly minor tweaks and bug fixes rather than any major new features (although I’m open to feature requests). Perhaps the most substantial changes are the addition of an INVENTORY TALL command and a thorough reworking of the SymConn extension to make it more usable. SymConn originally stood for ‘symmetrical connector’, and I’ve kept the name, but it should now be easier to use the extension to implement two-way connectors (Doors, Passages, Stairways and abstract TravelConnectors) that aren’t necessarily symmetrical. This is turn should make it easier for those using the extension to define doors, passages and stairways using only a single object rather than a pair of objects representing each side/end of the connector.

Among the tweaks I’m currently working on is taming the way adv3Lite interprets player input when the player character is in conversation with an NPC. There has been some justifiable criticism of the way adv3Lite takes any command it can’t otherwise understand as an implied SAY command during an ongoing conversation. This may be appropriate in some circumstances but often isn’t, so I’m trying to make this behaviour more easily customizable. The default behaviour in what I’ve now arrived at is that such input will only be treated as an implied SAY command if there are any SayTopics or DefaultSayTopics defined on the interlocutor’s Actor object or its current ActorState (if any), but to make it easy for game code to tweak this behaviour via a number of true/nil flag properties on the Actor object (or the Actor class).

This tweak uncovered another problem in that the Spelling Corrector became a little over-eager to “correct” the spelling of words the parser wasn’t then allowed to interpret as an implied SAY command so it matched the grammar of an implied QUERY command (i.e., something that might match a QueryTopic), which is unlikely to be at all what the player intended. My current fix is to disable the Spellling Corrector during conversations (i.e., when the player character has a current interlocutor), which I think produces better results, but again, it’ll be easy enough for game code to override this.

I’m also considering whether there might be a way to improve the library’s default response when it does interpret the player’s input as an implied SAY command that doesn’t match any SayTopics, to make it clearer to the player that this is how their input has been interpreted. Perhaps something along the following lines:

>FOO BAR WHATSIT
“Foo bar whatsit,” you say.

Jack does not respond.

The easiest way might be to make this the default behaviour of DefaultSayTopic, but this then relies on game authors supplying a DefaultSayTopic. OTOH this may not be an unreasonable solution, given that if game authors define no SayTopics or DefaultSayTopics at all, the parser now won’t interpret any input as an implied SAY command.

2 Likes

I think you may have gathered from some of my other recent posts that I’m not currently working out of GitHub (although that’s something I may get back to eventually). I’m aware that there were a number of issues surrounding PushTravel, which I’ve now fixed (by some fairly substantial changes to parts of the PushTravel handling to make it all a bit more robust). I originally sent Jim Aikin a file of mods that he could use with the existing library which effectively implement the changes I’ve now incorporated into version 1.6. Jim needed them for his IF-Comp entry, and so far as I’m aware he was happy that I’d fixed the problems he’d encountered; he expressed himself satisfied with his own testing and hasn’t reported any further issues encountered by his testers, so I hope and believe the PushTravel problems are now fixed.

But it sounds like there may be a number of other issues for which you want to suggest fixes. Perhaps you could start by simply posting the issues here, so I can check that they’re not things I’ve already fixed for the upcoming 1.6 release, and then we can work out a way you can let me know of any other fixes that remain.

2 Likes

Hi Eric! As far as what it does, I don’t think the system requires much more explanation than what I posted in the thread. The terse verb responses can be used within an object right alongside standard Lite coding, as shown in my small example. If a user chooses to define obj.kVerb or obj.nVerb, that handling will be used in preference to the obj.isVerbable flag. But if they write their own dobjFor block, that will always have first priority.
Users don’t ever have to see the ugly mess of macros that make it work, except for one small set that they need to use if they want custom verbs to also participate in the system. Those look like this:

DefineTAction(Ride) ; // VerbRules and such ;
modify Thing
	dobjFor(Ride) nkTouch(Ride)	//preCond touchObj for objs that allow Ride
	nRide = 'The obj isn\'t something you\'re likely to ride. '
;

The above definition is all that’s needed to allow users to drop nRide and kRide throughout their codebase; library verbs would already be available.
The four “prepackaged” macros that users would use are:

nkTouch(Customverb)
nkHeld(Customverb)
nkVisible(Customverb)
nkNoPrec(Customverb)

(There is also nk(Customverb), which could be used after a custom set of preconditions.)
And of course, the naming conventions could be changed to your liking.

The main thing to be said for now, is that the code isn’t finished. What is left is basically just grunt work though, going through each Lite library verb, and modifying its dobjFor/iobjFor with one of my macros that corresponds to its precondition set.
The other part that’s not finished is some choices about naming patterns for TI verbs. Because I wasn’t sure which naming pattern would be most generally appealing, I wrote two sets of macros and began to convert the library verbs in both ways, with the expectation that one set would be pitched or users could comment out the block they didn’t want. The details are explained more in the source code.

I don’t want to pitch work on you, so I’ll only send the unfinished source code if it is something you’re interested in putting a couple hours into, whether as extension or library integration. If not, I’ll probably eventually get around to finishing it some day. Like I said, I use my own version of the system in my adv3 game, and I’ve appreciated it enough that I wanted to share it with more of the TADS community.
Thanks again!

John Ziegler

1 Like

Hi John! I’d be interested to see what you’ve done so far, even if I don’t have the time to do much work on it right now. At the very least, I may be able to offer some suggestions or contribute to your thinking about choices for naming conventions on TI verbs and the like. My feeling remains that this is better offered as an extension rather than integrated into the main library, not least because if it’s part of the main library it’s one more thing that would need to be explained in the main library’s documentation, which many people find complicated enough as it is (but also because, if it’s intended to be optional, an extension would seem to be logical way of presenting it).

Thanks for your work on this and for your eagerness to share it with the adv3Lite authoring community.

Eric

~WRD0000.jpg

2 Likes

Hi Eric, I’m a new author around here and have been using your excellent LearningT3 manual for a while. Your announcement excites me; I’m glad there is still life in the adv3Lite project and I plan to convert my in-progress adv3 project over to Lite soon.

Your existing dropbox library download seems to 404, which is somewhat disappointing, but I figure I should probably wait for 1.6 anyway.

I’d like to second the above request to host adv3Lite on GitHub or a similar repository. I understand your apprehension to revive an old repository using a version control system you haven’t used in a while, but honestly, even if you wipe the old repository and just make 1.6 the “Initial Commit” of the new one, it would benefit the project in the long run. Bugfixes could be contributed by the community faster and in a more streamlined way, which would increase the survivability of the project in the future. Besides, making releases directly through GitHub would allow permalinks to library releases (as binaries and zip files can be arbitrarily attached), with little risk of a dead link in the future.

Anyway, thanks for the great library. Cheers

1 Like

The link mentioned further above works for me at the moment: Dropbox - adv3Lite15.zip - Simplify your life
Alternatively, the same version can be downloaded from the IF Archive here: http://ifarchive.org/if-archive/programming/tads3/library/contributions/adv3Lite.zip

2 Likes

Ah, thanks. I was trying to use the “dropboxusercontent” link from the blog and the LearningT3Lite manual.