Defining new actions (learning)

Hello! This is my first post, and AFAIK this is the best (only?) place to find help when coding in TADS3. (BTW, thanks to Michael J. Roberts and Eric Eve for this great framework / documentation!)
I am following the Learning TADS 3 for adv3 PDF. I want to create a new custom action (PourOut), along two custom classes (Liquid and LiquidContainer). But instead of accepting the defined action for the LiquidContainer, the cannotPourMsg is printed.

Note that I am using the G-TADS Library for german translations. This is why the DefineTAction looks a bit different to what you might be familiar with. However, I don’t expect that to be problematic here.

class Liquid: Thing
    isLiquid = true
;

class LiquidContainer: RestrictedContainer
    dobjFor(PourOut)
    {
        verify(){}
        action(){
            for (obj in contents) {
                removeFromContents(obj);
            }
        }
    }
    canPutIn(obj){
        return obj.isLiquid;
    }
    getBulk(){
        local bulk = 0;
        for (obj in contents) {
            bulk += obj.bulk;
        }
        return bulk;
    }

;

modify Thing
    dobjFor(PourOut)
    {
        preCond = [touchObj]
        verify() {illogical(cannotPourMsg);}
    }
    cannotPourMsg = '{Der dobj/er} kann nicht ausgeschĂźttet werden. '
;

DefineTAction(PourOut);
VerbRule(PourOut)
    verb('schütt'|'gieß') dobjList prep('aus'|'weg')
    :PourOutAction
    verbPattern('wegzuschĂźtten/wegschĂźtten', '(was)')
;

Further, I define a LiquidContainer like so:

// [...]
++ LiquidContainer 'mittler Kanister' 'mittler[^] Kanister'
    "Dieser Kanister kann 3 Liter FlĂźssigkeit fassen. "
    bulkCapacity = 3
    isHim = true
;
+++ Liquid 'wasser' 'wasser'
    bulk = 3
;

Now, when I compile and run the game, and trigger the “PourOut” Action on a LiquidContainer, the cannotPourMessage is printed:

schĂźtte den mittleren Kanister aus
Der mittlere Kanister kann nicht ausgeschĂźttet werden.

Any ideas what might be the problem? Your help is highly appreciated, cheers!

EDIT: I updated the code to reflect some changes I made - they do not change the behaviour, however.

Note that when I comment out the verify() method in the Thing class, the output changes to “Der mittlere Kanister kann nicht geschüttet werden” (which is a subtle difference to the cannotPourMsg, and makes me believe I made some mistake in the action definition or verb rule part…

3 Likes

Welcome to TADS 3! I’m away from a computer but I’ll look at it later if no one else jumps in sooner…

Is the “mittler Kanister” defined the same way?

Ah sorry, I posted the “groß Kanister” instead haha.

I already changed a bit of the code, and I will edit my original Question to reflect the changes (The issue persists). Thank you for pointing it out.

1 Like

I don’t know german, but two things:

IIRC that by TADS uses ascii by default (and the ß in große isn’t part of the US-centric ASCII set) so, tried to add #charset [german] as the very first line of your source ? (or test with grosse instead of große)

Second: the isHim surprised myself a bit; I’m under the impression that germanic language has all three genders, male, female and neuter. I’m correct ? if yes, try to comment out isHim, perhaps confuses the german-language library… (yes, as I don’t know german, don’t know much about the german-language translation of adv3…)

Best regards &c. from Italy,
dott. Piergiorgio.

2 Likes

Thank you for your input. The german language library (G-TADS) uses #charset "iso-8859-1", which is also included in the file. The LiquidContainer is also correctly selected, as when I issue untersuche Kanister (which is the german version of “examine …”) it correctly prints it’s desc.

You are right that german has all three genders. isHim (and isHer, respectively) is used to tell the compiler (or is it the parser?) the gender of the Thing. Without it, it would assume a neutral gender, which is wrong.

What I am most confused about is that it both understands the intent (schĂźtte ... aus) as well as the target ([mittlerer] Kanister), but apparently it does not accept the action for this specific target (either because it prints the CannotPourMsg defined in Thing, or [when the Action handling is commented out in Thing] due to another reason not apparent to me at this point.

A final note I want to add for those who look into the G-TADS definitions:
I double checked the VerbRule, and realized that there are different definition styles in the de_de.t file. So I changed my definition from

verb('schütt'|'gieß') dobjList prep('aus'|'weg')

to

verb('schütt','gieß') dobjList prep('aus','weg')

to no avail (it seems to make no difference) :confused:

As the parser interprets the intent (schĂźtt) correctly, I will for now leave the definition and look into how to debug TADS applications.

Still happy about any hints, and thank you once more for your input Piergiorgio

2 Likes

Is it possible your PourOut grammar overlaps with the library grammar of Pour or PourOnto? Perhaps make LiquidContainer pass verify for all the stock Pour forms and see if it gets by?

2 Likes

Here’s what I did: I more or less copied the code you provided into a skeleton game, but used en_us. I just changed the verbRule to comply with conventions. I located the LiquidContainer directly in a Room. I added the word ‘giess’ to the grammar of the PourOut verb, and in a test run I typed ‘giess Kanister’. It passed verify, as expected. Typing ‘giess window’ printed the “nicht ausgeschüttet” message.
This makes me suspicious that perhaps the grammar you are using is involuntarily invoking a library verb (I wouldn’t know, in the German version).
You could test this by something like

class LiquidContainer
   dobjFor(Pour) { verify { illogical('Pour fail'); } }   
   dobjFor(PourOnto) { verify { illogical('PourOnto fail'); } }
   dobjFor(PourOut) { verify { illogical('PourOut fail'); } }

unless you can manage to debug print the gAction that’s taking place when the fail message appears.

2 Likes

Oh wow, I was not aware that there is a PourAction at all - that was it. The confusion came by the fact that the cannotPourMessage indeed was printed, but for different reasons than I thought (that ist, triggered by the PourAction instead the PourOutAction).

Thank you John Ziegler for your time and support ! Happy coding

3 Likes

This may be a given, but you’ll also want some text output if PourOut reaches the action phase :slightly_smiling_face:
You may also want to include the German words for “empty” and “dump” in the grammar if they’re not already covered… I had some LiquidVessels in my game as well.
Also may already be in your plans, but you’ll want to provide some kind of rational message for when players try to put Liquids in ordinary Containers…

2 Likes

I felt the same way when I began!

1 Like