[adv3Lite] License Question; Changing Code for Teaching

This may be seen as an utterly idiotic question but I ask it because I work in the open source community a lot and checking on this kind of stuff is ingrained.

Context: I’m already doing some classes on Inform 7 but something like TADS 3 tends to get more traction from a selling standpoint, because it looks and acts more like a “traditional” programming language. I’m going to be introducing TADS 3 and many of the class attendees will also be using Inform 7 or at least coming from those classes. I’m most likely going to use the adv3Lite library.

Problem: As I brought up previously, however, the term “Doer” just makes no sense to me and is not an intuitive wording. I understand the likely rationale for why it was named as such, but everything about it screams Rules or something like that.

Reason for Post: So what I’d like to do is present a modified version of adv3Lite that changes that phrasing, which will essentially be a forked library available on GitHub. I want to make sure there are no concerns about that.

No concerns, but all the documentation refers to Doer, and once you fork a different version on adv3Lite on GitHub, it be difficult to keep it in sync with future updates to adv3Lite that still use the name Doer. But those are practical difficulties you’d need to overcome, not objections on my part to your doing it, so do feel free to go ahead.

That said, it may be that the only change you actually need to make to the adv3Lite library if you want to use a different name for the Doer class is to add:

class Rule: Doer
;

Then all the game code you write can use the name Rule in place of Doer without your having to fork the library.

I should really update the advice I gave in my previous post in the light of more recent developments.

The next release of adv3Lite will include a rules extension in which Rule and RuleBook will be used as names of classes. It would therefore be a really bad idea to rename ‘Doer’ to ‘Rule’, since that would prevent anyone from using the rules extension.

Work on the new rules extension is well underway; basically I just need to finish off the documentation and do some more testing.

Certainly Doers will look quite a bit like the new (fully optional) Rules, but I intend to explain the difference between them in the documentation. If you’re planning to use both in the same game, Doers are best restricted to either stopping an action in its tracks or changing it to another action. Anything else is probably better done with Rules (assuming you want to use them at all).

For example it will be better to do this:

jumpRules: RuleBook
;

+ Rule
    where = firstRoom
    
    follow()
    {
        "You jump pointlessly. ";        
    }
;

+ Rule 
    where = nextRoom
    
    follow()
    {
        "You jump fruitfully. ";        
    }
    
    execAfter = [regionRule]
;

+ Rule
    follow()
    {
        "You jump energetically. ";       
    }  
;

+ regionRule: Rule 
    where = someRegion
    follow = "You jump and fall over! "
;


modify Jump
    execAction(cmd)
    {
        jumpRules.follow();
    }
;

Than to write the equivalent Doers, the reason being if you do this kind of thing:

Doer
    where = firstRoom
    
    execAction(c)
    {
        "You jump pointlessly. ";        
    }
;

...

Despite apperances, no Jump action is ever executed, which means that any beforeAction() or roomBeforeAction() method testing for a Jump action will never find it (which could lead to hard-to-find bugs). You could call the beforeAction processing manually from each Doer, to be sure, but that’s quite a lot of extra work.

So, given that the new rules extension will be available from the next release (and can be previewed on GitHub), I think it’s best to keep the names Rule and Doer conceptually distinct.

I agree that the term “Doer” seemed clunky to me at first. Off-putting, in fact – but then, I’m used to the T3 verify()-check()-action() scheme, so at first I didn’t see a need for Doers.

Per Eric’s suggestion, how about replacing the class name with ActionHandler?

If Jeff wants to call it something else, that’s up to him, although I’d question whether it was worth forking the library just for a single class name. At this point, I really don’t think it’s worth changing the name in standard adv3Lite at this stage (a) because it’s been in use quite a while so (b) changing it would break a lot of existing game code and © would probably confuse more people than it helped (besides (d) being a recipe for a whole raft of unforced bugs in the library and the documentation).

If nothing else, at least ‘Doer’ has the merit of being brief!

This sounds like a good enhancement. Partly cosmetic, in that it will make transitioning easier for I7 authors, but very likely there will be occasions when it will make the game code easier to write.

But wouldn’t adding inherited(c) to the Doer code also solve that problem?

Jerry

Not if the code in the Doer’s execAction() method is meant to replace what the action would normally do, since then you’d get both the Doer’s version and the action’s normal version. You could solve the problem by adding c.action.beforeAction() to the Doer code, it’s just a bit of hassle if you have to do it to a lot of Doers. In any case, the example was only intended as illustrative.

Right. I’m sure most adv3Lite games will be perfectly able to do quite well without it, but then it’s only extension, and some people might find it useful for certain purposes. I’m really just rounding out the set of I7 features that might be worth having as I7 extensions in case anyone wants them. The thing about extensions is you can always ignore them if you don’t!

By the same token I’m also working on a relations extension to allow I7-style relations, just in case anyone might one day find them useful in an adv3Lite project. This will allow you to set up relations with statements like:

loving: Relation 'loves' 'lovedBy' @manyToOne;

relate(tom, 'loves', mary);

And then later test them with statements like

related(tom, 'loves', mary); // returns true
related(tom, 'loves'); // returns [mary]
related(mary, 'loved by') // returns [tom]

Of course this is only a toy example, and I don’t know how useful many people will find it, but it should end up providing most of the functionality of I7 relations, including pathfinding through relations.

From your example, it appears you’re planning to use the I7 methodology of allowing the Rulebook to start by considering the most specific rules and then falling through to the more general rules. This is a sensible method in most cases, as it allows the author to add Rules to a Rulebook (using a template with @jumpRules as the location property, possibly) without worrying about putting the Rules in a precise order.

Have you considered adding an “order” property to the Rules class, by analogy with the menuOrder property in the menu system, so as to allow the author to create a pre-sorted list order if it proves necessary?

Yes, indeed, that’s already there. You can override the default ordering of rules either by using their priority property or by specifying that one rule must come before or after another specified rule.