Ordering <something>

I’m looking to implement the following:

ORDER something

… where something is hopefully obvious to the player, but I need it to be flexible enough to trap some other responses.

I could have hidden objects in the location and trap the ORDER verb there, but I was wondering if there was a different way to accomplish this, like CONSULT topic.

Any ideas?

Thanks!
– Mike

One way to do it … try searching for “scope” in the docs (using the Search field in the upper right corner of Workbench). You’ll find that the Technical Manual has an article called “Redefining Scope.” This will show you a way to put any object in the game in scope for purposes of your new verb.

Another way is using Topic objects, which need not be present in the model world at all. The Tech Manual’s “How to Create Verbs” article discusses creating verbs that work with Topics.

I’m not clear on what you’re after, but you can use a LiteralAction to capture undirected free-form text from the player. Possibly this is too flexible for your needs.

In the example below, a few special cases are trapped and handled, and the rest are diverted to a secondary action for standard processing.

VerbRule(Order)
	'order' singleLiteral
	: OrderAction
	verbPhrase = 'order/ordering (what)'
;

VerbRule(OrderThing)
	'orderthing' singleDobj
	: OrderThingAction
	verbPhrase = 'order/ordering (what)'
;

DefineLiteralAction(Order)
	execAction() {
		switch(getLiteral.toLower) {
			case 'lunch':
			case 'sandwich':
				"You place an order for a sandwich. ";
				break;
			case 'launch':
			case 'attack':
			case 'strike':
			case 'nuclear strike':
				"You advise the generals to launch at will. ";
				break;
			default:
				local toks = Tokenizer.tokenize('orderthing ' + getLiteral.toLower);
				executeCommand(gActor, gActor, toks, true);
				break;
		}
	}
;

DefineTAction(OrderThing);

modify Thing
	dobjFor(OrderThing) {
		verify() { illogical('You are not sure how to order that. '); }
	}
;

Jim, thanks – I’ve read that technical article more times than I care to admit, but it wasn’t until I read bcressey’s response that I realized I was approaching it from the wrong angle.

Bcressey, thanks for that; it’s what I’m looking for. Since I plan on lifting most of that code, I will add you to the Credits list. :slight_smile:

– Mike

Please correct me if I’m wrong, but my impression is that Ben Cressey’s code for DefineLiteralAction will work correctly for ‘order sandwich’ but will fail if the player types ‘order a sandwich’. The advantage of using Topic objects, I’m pretty sure, is that things like articles and adjectives can be understood and handled.

Happy to help!

I noticed some artifacts in the output when using UNDO with the above code. Replacing the OrderThing stub with this code should fix it:

DefineTAction(OrderThing)
	includeInUndo = nil
	actionTime = 0
;

That way the extra action doesn’t count against the player’s time, and undo will skip over it.

The simple switch statement in the execAction can be replaced with string methods to do more sophisticated matching. Also, the VerbRule can be expanded to handle articles, so you don’t have to worry about them when processing the literal.

VerbRule(Order)
	'order' | ('order' ('a' | 'the' | 'an' | 'some' )) singleLiteral
	: OrderAction
	verbPhrase = 'order/ordering (what)'
;

You’re right that this approach is not a good general practice. The alternative approach I came up with - an invisible actor who comes into scope during Order actions, and responds to topics by executing some code - strikes me as too convoluted, though it would leverage the parser rather than doing an end-run around it.

Does ORDER mean ORDER A BEER? In that case, I think it’s more natural to implement it as ASK WAITER FOR BEER (and remapping ORDER to it.) If, however, it means ORDER THE LIEUTENANT TO RETREAT, then bcressey’s advice is probably the way to go.

Good points, considering I was vague in my original post.

Since I only need the command to work one time – and it’s an alternate to the preferred method – I can certainly use the sample code above.

Heh. Well, therein lies the rub. If Sherwin had made the order taker a waiter, or a bartender, or human for that matter, I completely agree with the remapping… :wink:

– Mike

Note that this code doesn’t work (ORDER LUNCH results in “The story doesn’t understand that command.”) and if just ORDER is entered, it sorta crashes. It only works if you type >ORDER A followed by the dobj.

Sorry that I am posting this without the fix; I would if I could, but I can’t so I didn’t. Or something like that…

In any event, because I need this for an isolated event, I can live with the existing code.

(I figured I would mention the code issue above in case somebody else wanted to use it…)

– Mike

(EDIT: I felt bad about not really trying to fix it, so I did)

This works instead:

VerbRule(Order) ('order' singleLiteral) | ('order'  ('a' | 'an' | 'the' | 'some') singleLiteral): OrderAction 

I believe that’s because you forgot to allow “nothing” as a possibility, and also make the single ‘order’ case depend on the singleLiteral. What you want is:

  ('order' | ('order' ( /*nothing*/ | 'a' | 'the' | 'an' | 'some'))) singleLiteral

There are many ways to write the above rule, mind you. For examle a cleaner form:

  ('order' ( /*nothing*/ | 'a' | 'the' | 'an' | 'some')) singleLiteral

(No guarantees though; I didn’t actually test this, but I’m sure it should work :slight_smile:)

The above translates to:

ORDER followed by nothing or A or THE or AN or SOME and ending with a singleLiteral.

It’s pretty much standard EBNF (it was chosen because it’s well known), so the same rules apply.

Thanks for the fix! I like that second form; I’ve tested it and it seems to work fine.

Has it really been 8 years?

Well, I’m pretty sure this is the year that the code @bcressey and @RealNC helped develop in this thread for ORDER something’ get published.

Fortunately, there’s a lot more code I added after this thread so it’s not a one turn game!

A belated thanks to both of you for your help back then!

– Mike

4 Likes