If you were prepared to allow ‘push’ as a synonym for ‘pull’ here the solution would be simple; simply define canPushTravel = true on your little red wagon.
If you really need to distinguish ‘push’ from ‘pull’ in this situation, then to do it “properly” would, I’m afraid, require a lot of extra work, since this is something the library doesn’t cater for.
First, you will need to go through all the VerbRules that have names starting with PushTravel (such as PushTravelClimbUp) and modify them so that they no longer refer to words like ‘pull’ and ‘drag’. You will also have to decide whether you want ‘move’ to mean ‘push’ or ‘pull’. For example:
VerbRule(PushTravelClimbDown)
('push' | 'move') singleDobj
:
;
And so on for all the rest.
Then you would need to copy and paste all the PushTravelXXX actions and VerbRules from actions.t and grammar.t into your own game code and rename them to PullTravelXXXX, as well as adjusting the VerbRules so they all match ‘pull’ and ‘drag’ rather than ‘push’.
Finally you would need to modify Thing with copy and pasted versions of all the dobjFor(PushTravelXXX) sections turned into dobjFor(PullTravelXXX) sections, as well as new versions of some of the supporting methods such as verifyPushTravel() adapted to verifyPullTravel(). You may also need to search for iobjFor(PullTravelXXX) methods on other classes and do the same.
In other words, this is one heck of a lot of work just to get PUSH WAGON EAST and PULL WAGON EAST to mean different things.
There are, however, a couple of potential shortcuts you can look at which could save you this enormous amount of effort.
First, if there are no objects in your game that you want to be able to push anywhere, you can simply adapt the existing PushTravel framework to act as PullTravel. To do this you would first modify all the VerbRules mentioned above to accept only ‘pull’ or ‘drag’ but not ‘push’. You would then override all the message properties on Thing that relate to PushTravel (look for the verifyPushTravel() method on Thing and find the messages that follow) to refer to pushing rather than pulling. You’d still need to define canPushTravel = true on the wagon, of course; effectively you’d still be using the various PushTravel actions but you’d be making them look like PullTravel ones.
Or second (and this is what I would do), simply define canPushTravel = true on the wagon and override its various PushTravel message properties so that they refer to pulling rather than pushing. Forcing the player to type PULL WAGON EAST rather than PUSH WAGON EAST when both would otherwise end up doing the same thing is almost certainly more trouble than it’s worth [But see bellow for a possible kludge to handle this].
The two methods you’d most need to override on the wagon are beforeMovePushable(connector, dir) and describePushTravel(via), which might become (for example):
beforeMovePushable(connector, dir)
{
if(connector == nil || connector.ofKind(Room))
"{I} pull{s/ed} {the dobj} <<dir.departureName>>. "";
else
describePushTravel(viaMode);
}
describePushTravel(via)
{
/* If I have a traversalMsg, use it */
if(gIobj && gIobj.propType(&traversalMsg) != TypeNil)
"{I} pull{s/ed} {the dobj} <<gIobj.traversalMsg>>. "
else
"{I} pull{s/ed} {the dobj} <<via.prep>> {the iobj}. ";
}
Alternatively, you might define a CustomMessages object that only takes effect when the direct object is your wagon:
CustomMessages
active = (gDobj == redWagon)
messages = [
Msg(before push travel dir, '{I} pull{s/ed} {the dobj} {1}. '),
Msg(push travel traversal, '{I} pull{s/ed} {the dobj} {1}. '),
Msg((push travel somewhere, '{I} pull{s/ed} {the dobj} {1} {the iobj}. ',)
]
;
You might need to do a bit more than this to get every reference to pushing changed to pulling on the wagon, but that should be enough to point you in the right direction.
Finally, there may be a slightly kludgy way to refuse the command PUSH WAGON EAST (etc.) while still using the second and simpler option above. I think you may be able to look at gCommand.verbProd.tokenList to see what the player typed. That being so, it may be possible to do something like this on your wagon:
verifyPushTravel(via)
{
if(getTokVal(gCommand.verbProd.tokenList[1]) == 'push')
implausible('{The subj dobj} {can\'t} be pushed anywhere. ');
inherited(via);
}