StrikeWith Action

Hello,

The puzzle I’m working has the PC making a light source and then lighting it.
When the PC tries Strike steel with flint or vice versa, a standard response results.
It’s best to avoid pointless violence.
I’d like to override that and allow the action to occur.
I have included the following (some of which I don’t understand).

DefineTIAAction(StrikeWith)

;
VerbRule(StrikeWith)
    'strike' multiDobj 'with' singleIobj 
    : VerbProduction
    action = StrikeWith
    verbPhrase = 'strike/striking (what) (with what)'
    missingQ = 'what do want to strike; what do you want to strike it with'
;

 modify Thing
    dobjFor(StrikeWith) asDobjFor(StrikeWith)
    iobjFor(StrikeWith) asIobjFor(StrikeWith)
    aobjFor(StrikeWith)
    {
        preCond = [objHeld]
        
        verify() 
        { 
            illogical('{I} {can\'t} use {the aobj} to strike that. ');
        }
    }
;

All help is appreciated, as always.
Deborah

2 Likes

Ohhhhh I’ll need to get the documentation, but I think what’s happening is the Attack or AttackWith actions are matching with your command before your StrikeWith action gets a chance to.

There’s a way to give StrikeWith a match priority but I’ll need a moment to check the documentation.

1 Like

Try this:

By adding a priority = 60, it should try to match before similar actions do.

2 Likes

Only got a minute here , but I note that your action should be a TIAction, not a TIAAction, as you have no aobj defined in the grammar…

2 Likes

I have been inching along here and have made progress. Thank you all for your help.
Right now, I am referencing the ADV3LITE manual, about 3/4 down on the page, Defining TIActions. Which seems to be exactly what I need.

When I have the flint and amulet in my inventory and try the command

Strike amulet with flint

It fails on the verify stage and I’m not sure why. Again, I am just starting to understand this and have only a few hours each week to spend on it. :frowning:

DefineTIAction(StrikeWith)
   resolveIobjFirst = nil
;

VerbRule(StrikeWith)
    'strike' singleDobj 'with' singleIobj 
    : VerbProduction
    action = StrikeWith
    verbPhrase = 'strike/striking (what) (with what)'
    missingQ = 'what do want to strike; what do you want to strike it with'
    priority = 60
;
modify Thing
isStrikable = nil
    dobjFor(StrikeWith)
     {
              preCond = [touchObj]
       verify() 
       {
        if(!isStrikable)
         illogical('{That dobj/he} {is}n\'t something {you/he} can strike direct. ');
       }
     }
     iobjFor(StrikeWith)
     {
              preCond = [touchObj]
       verify() 
       {
        if(!isStrikable)
         illogical('{That iobj/he} do{es}n\'t look very useful as
                    a striking tool indirect. ');
       }
     }
;
++ flint: Thing 'flint;;;them '
"Strike the flint against the fire amulet to create a spark.  "
bulk = 0.2
isStrikable = true
iobjFor(StrikeWith)
   {
           
      check()
      {
           //if(amulet.isIn(me))
            "You'll need to find something else, too. ";
      }
      
      action()
      {
           "Using {the iobj} {i} with{s/d} {the dobj} creates a spark. ";
           
      }
   }

;
++ amulet: Thing 'fire steel amulet; steel; amulet'
"Fire steel is a shaped piece of metal for striking against flint to cause a spark. 
There should be something flammable nearby to strike the spark towards. "
bulk = 0.2
isStrikable = true
iobjFor(StrikeWith)
   {
           
      check()
      {
           //if(flint.isIn(me))
            "You'll need to find something else, too. ";
      }
      
      action()
      {
           "Using {the iobj} {i} with{s/d} {the dobj} creates a spark. ";
           
      }
   }
;

Output:
strike amulet with flint

You’ll need to find something else, too.

strike flint with amulet

You’ll need to find something else, too.

2 Likes

Is there a definition for your me object above this? Because + before an object means that whatever is defined above that will be its location, and ++ means you’re nested two objects deep with this location.

There’s a chance that the game is attempting to set your StrikeWith action as the flint’s location, which means that if(flint.isIn(me)) will fail.

Additionally, I noticed that both if statements in your check() blocks are commented out:

//if(amulet.isIn(me))
  "You'll need to find something else, too. ";

…which means that "You'll need to find something else, too. "; has nothing to stop it from running. If anything prints to the screen from a check() block, the action fails and comes to a halt. When running your game, the interpreter is basically seeing this:

check()
{
      "You'll need to find something else, too. ";
}

…so the action never succeeds for those objects.

Oof, that’s valid. I also know it’s extremely frustrating, too. You’re learning quickly and demonstrating admirable patience with this, for what it’s worth.

2 Likes

Jess,
The flint and amulet are on a shelf in a room, so yes, nested.
The if condition was the key. I had commented it out because as it was written, it wasn’t making a difference. This, however, works.

if(!flint.isIn(me) && (!amulet.isIn(me)))
"You'll need to find something else, like flint. ";

Thanks for all your help! It’s going to be a rainy day, maybe I will get to spend some quality time with my copmuter. :+1:t3:

2 Likes

I’m waaaay late in my reply, but if you’re using adv3Lite, you should be aware of Doers, which can step around this problem:

Doer 'strike amulet with flint'
  execAction(cmd) {
    // do custom action
  }
;

The “custom action code” can print a result and update state changes directly to the necessary objects.

3 Likes

Jim, thanks for this.
I am still learning. I do have it working with the VerbRule syntax so I am going to stick with that for now.
I appreciate everyone’s help. :slight_smile:
Some of your old posts from years ago have also helped me (as have many others).

Deborah

1 Like