You want to define a new action that takes both a direct and indirect object. In TADS3 the macro you probably want for this is DefineTIAction.
Declaring the action itself is straightforward:
DefineTIAction(RemoveWith);
The you need to declare a VerbRule for the action, something like:
VerbRule(RemoveWith)
'remove' singleDobj 'with' singleIobj
: RemoveWithAction
verbPhrase = 'remove/removing (what) (with what)'
omitIobjInDobjQuery = true
askDobjResponseProd = singleNoun
askIobjResponseProd = withSingleNoun
;
In this case the askDobjResponseProd and askIobjResponseProd properties are superfluous, because there’s an existing action (RemoveAction) that will end up being matched if the player uses >REMOVE [object] without an indirect object. If you don’t want that to happen (and you want to disable the stock RemoveAction as well) let me know.
Adding a new action you probably want to declare a stock behavior for it on Thing, to provide a useful failure message for objects that don’t implement it.
First declare the failure messages (you can hardcode them, but creating new library messages and using them makes maintenance easier):
modify playerActionMessages
cantRemoveWithThat = '{You/he} can\'t remove {that dobj/him}. '
cantRemoveWithThatIobj = '{You/he} can\'t remove anything
with {that dobj/him}. '
;
…and then add the default handing to Thing:
modify Thing
dobjFor(RemoveWith) {
verify() { illogical(&cantRemoveWithThat); }
}
iobjFor(RemoveWith) {
verify() { illogical(&cantRemoveWithThatIobj); }
}
;
I don’t know what kind of behavior you want to implement, but you can now individually override the dobjFor(RemoveWith) and iobjFor(RemoveWith) stanzas to create different results when the action is used with different direct and indirect objects. Example:
pebble: Thing 'small round pebble' 'pebble'
"A small, round pebble. "
dobjFor(RemoveWith) {
verify() {}
action() {
"This is the pebble success message. ";
}
}
;
rock: Thing '(ordinary) rock' 'rock'
"An ordinary rock. "
iobjFor(RemoveWith) {
verify() {}
action() {
"This is the rock success message. ";
}
}
;
In this case the pebble can be used as the direct object and the rock can be used as the indirect object and each will display a message when this is done.
Putting this all together:
#charset "us-ascii"
#include <adv3.h>
#include <en_us.h>
modify playerActionMessages
cantRemoveWithThat = '{You/he} can\'t remove {that dobj/him}. '
cantRemoveWithThatIobj = '{You/he} can\'t remove anything
with {that dobj/him}. '
;
startRoom: Room 'Void' "This is a featureless void. ";
+me: Person;
+pebble: Thing 'small round pebble' 'pebble'
"A small, round pebble. "
dobjFor(RemoveWith) {
verify() {}
action() {
"This is the pebble success message. ";
}
}
;
+rock: Thing '(ordinary) rock' 'rock'
"An ordinary rock. "
iobjFor(RemoveWith) {
verify() {}
action() {
"This is the rock success message. ";
}
}
;
+stone: Thing '(nondescript) stone' 'stone'
"A nondescript stone. "
;
versionInfo: GameID;
gameMain: GameMainDef initialPlayerChar = me;
DefineTIAction(RemoveWith);
VerbRule(RemoveWith)
'remove' singleDobj 'with' singleIobj
: RemoveWithAction
verbPhrase = 'remove/removing (what) (with what)'
omitIobjInDobjQuery = true
askDobjResponseProd = singleNoun
askIobjResponseProd = withSingleNoun
;
modify Thing
dobjFor(RemoveWith) {
verify() { illogical(&cantRemoveWithThat); }
}
iobjFor(RemoveWith) {
verify() { illogical(&cantRemoveWithThatIobj); }
}
;
Transcript:
Void
This is a featureless void.
You see a stone, a pebble, and a rock here.
>remove stone
(from the void)
Taken.
>undo
Taking back one turn: "remove stone".
Void
This is a featureless void.
You see a stone, a pebble, and a rock here.
>remove rock with stone
You can't remove that.
>remove pebble with stone
You can't remove anything with that.
>remove rock with pebble
You can't remove that.
>remove pebble with rock
This is the rock success message. This is the pebble success message.