Moving a Trackball

Working in TADS 3 there are often times when I find myself faced with something that I know the system can already do, but I can’t figure out exactly how to get my hands on the functionality. Usually I can muddle through, but this time I’m stumped. I’ve searched the various docs, looked in the technical manual…

Okay, what I have is a machine with a trackball, which the player can move to produce a certain result (this result is not, of course, the actual relocation of the trackball). I’ve also, for completely separate reasons, implemented the directions “left” and “right” in the game. It seems to me that using existing verbs I should be able to handle the following player commands:

But… how?

The best I’ve been able to do so far is:

In the first case I’ve got the action method for the PushTravel verb, but how do I find out what direction the player is trying to move it in?

In the second case, how do I tweak the parser to understand PUSH (object) TO (object) in the same fashion as PUSH (object) (direction)?

And having solved the second case, will the third just fall out? I notice that T3 in general doesn’t seem to like articles being used with directions (for example, >GO TO THE NORTH results in “You see no the north here.”)

Does the following accomplish what you want?

[code]DefineTAction( MoveLeft );
DefineTAction( MoveRight );

VerbRule( MoveLeft )
(‘move’ | ‘push’) singleDobj ( | ‘to’ ‘the’) ‘left’
: MoveLeftAction
verbPhrase = ‘move/moving (what) left’
;

VerbRule( MoveRight )
(‘move’ | ‘push’) singleDobj ( | ‘to’ ‘the’) ‘right’
: MoveRightAction
verbPhrase = ‘move/moving (what) right’
;

modify Thing {
dobjFor(MoveLeft)
{
preCond = [touchObj]
verify()
{
illogical('There’s no obvious way to do that. ');
}
}

dobjFor(MoveRight)
{
	preCond = [touchObj]
	verify()
	{
		illogical('There\'s no obvious way to do that. ');
	}
}

}[/code]

Edit:
As to T3 not accepting GO TO THE NORTH and MOVE OBJ TO THE NORTH, it’s rather easy to enable that, since all that needs to be done is to modify the VerbRule for the actions in question. For GO:

// The default is: 'go' singleDir | singleDir modify VerbRule( Travel ) 'go' ( | 'to' 'the') singleDir | singleDir : ;

And for MOVE:

// The default is: ('push' | 'pull' | 'drag' | 'move') singleDobj singleDir modify VerbRule( PushTravelDir ) ('push' | 'pull' | 'drag' | 'move') singleDobj ( | 'to' 'the') singleDir : ;

Thanks for trying, but unfortunately not.

Regardless, even if it did, I’d have to include equivalent verbs for every other direction, otherwise the parser might come up with “The trackball cannot be moved.” when it obviously can, just because they tried moving it “north” or “starboard”. (I could just have one verb for all directions I don’t want covered, but I’d still have to make sure to include all their abbreviations etc.)

And in any case, this is kind of like admitting defeat. The handling is already there. The PushTravel verb exists, as does the MoveTo verb.

Library diving time, I guess.

UPDATE:

Getting somewhere:

That’s because I explicitly didn’t allow that in the example VerbRule, since “move trackball to left” doesn’t look like correct English to me. But nonetheless, it can be allowed with:

('move' | 'push') singleDobj ( | 'to' ( | 'the')) 'left'

Btw, if the nesting is too confusing, you can also state every possible syntax explicitly. The above is equivalent to:

('move' | 'push') singleDobj ('to' 'the' 'left' | 'to' 'left' | 'left')

That shouldn’t happen; it works correctly here with the above VerbRule.

It’s not admitting defeat, because “left” and “right” are not travel directions. At least that’s how I understand it. When you say MOVE TRACKBALL LEFT, I assume you mean rotating the trackball counter-clockwise instead of moving the trackball to the Room left of the current location. Because “left” in this context is not a travel direction, the standard PushTravelDir action should not be used for this because it doesn’t seem logical.

But if you still want to do it using travel directions, then you can implement a PushTravel handler in your trackball object like this:

	dobjFor(PushTravel)
	{
		verify()
		{ }
		
		action()
		{
			switch (gAction.getDirection()) {
			  case northDirection:
				// ...
			  case southDirection:
				// ...
			  // Similar for eastDirection, northwestDirection, etc.
			}
		}
	}

Now we’re getting somewhere! :smiley:

I just found the gAction.getDirection(), myself. Think I came pretty close to crush depth on my dive… Ultimately I only found it because I stumbled on the ThrowDir verb and it handles the specific case of “throw down”. My complete solution is now:

modify VerbRule(PushTravelDir)
    ('push' | 'move') singleDobj (| 'to' | 'to' 'the') singleDir
    :
;

//elsewhere, nested in another object:
++Trackball: Component 'track trackball/ball' 'trackball'
    "Pretty old-school, but it serves a purpose. "
    dobjFor(PushTravel)
    {
        verify(){}
        check(){}
        action()
        {
            //more handling here, obviously
            "I move the trackball <<gAction.getDirection().name>>. ";
        }
    }
;

Ah, but we allow players to type “take coin” even though the correct English is “take the coin”. :stuck_out_tongue:

But the main reason I want to include this phrasing is because the T3 library has default handling for “push/move (object) to (object)” - meaning that unless we handle this case the player will get the “I see no left here.” response - something that will only confuse them.

It may not seem logical in terms of the internal logic of the game as privy to the coder, but in terms of the actions we’re teaching the player to use, it is. The player can already type “push X left” in other contexts, and creating an additional context only creates the possibility for confusion, misunderstandings and bugs. It’s similar to how “press button” and “press murder suspect” are very different actions, but having two different “press” verbs floating around is just asking for trouble.

Glad you solved it.

Though now you have to deal with players trying to ROTATE TRACKBALL RIGHT (and TURN, ROLL, maybe more?) :mrgreen: That won’t fit nicely with travel directions. So you’ll probably end up implementing those verbs anyway.

If players want to roll things in travel directions, who am I to criticise their phrasing. :smiley:

And… I hate to be yet another TADS user asking this kind of question, but… how did you know you know about gAction.getDirection()? Is it just a case of being really experienced with the library or is there an obvious process to take to see how verbs with directions work? As I mentioned, I only reached it by stumbling onto a similar but unrelated verb.

I didn’t know about it beforehand. Since I needed to know how the "move " action is defined, I looked it up in actions.t, where all actions are defined. I opened that file and did a text search for “(Move”. Only three matches, none of them what I wanted, so I searched “(Push” next. One of the matches was “DefineTAction(PushTravel)” and directly below it another match, “DefineAction(PushTravelDir, PushTravelAction)”. And there was the definition of getDirection(): “getDirection() { return dirMatch.dir; }”

THROW DOWN
Violence isn’t the answer to this one.

[No, I don’t have anything to contribute. Carry on.]