I7: How do I issue a 'get all' from within the source?

The subject line is most of the question.

But also - can I store the action ‘get all’ in a table? I’m storing lots of actions in general, but I’m concerned I won’t be able to store ‘get all’ as a discrete action, since it seems to just generate a pile of separate ‘get’ actions. But I can get around not being able to store it with another mechanism I’ve made, if I can at least have the source ask for a ‘get all’.

-Wade

Try something like

Repeat with McGuffin running through visible things: Try taking McGuffin;

And I suppose if you want to store it in a table as a single action you could do it like this:

Grabbing is an action applying to nothing. Carry out grabbing: Repeat with McGuffin running through visible things: Try taking McGuffin;

and then put “Grabbing” in your table.

I don’t know if that’s what you’re looking for, though.

That’s the only workaround I thought of, but it’ll be mildly depressing if that’s what it’ll have to be.

-Wade

My overwrought solution is below. See the comments for details.

More info about what you’re planning to do would help.

Under what circumstances will you need to get all? In the middle of other multiple actions? Do actors other than the player need to get all?

Also, note that if you store the individual get actions generated by “get all” and play them back later, the meaning of “all” will be based on the game state when the command was originally issued. If you instead store a single “get all” and play it back later, the meaning of “all” will be based on the game state at that later time.

Test Chamber is a room.

The ball is a thing in Test Chamber.
The glove is a wearable thing in Test Chamber.
The player carries a coin.
A rock is a kind of thing.
5 rocks are in Test Chamber.

A room called Other Room is east of Test Chamber.
The balloon is a thing in Other Room.
	
[Setting multiflag prevents paragraph breaks in between our take actions below.]
multiflag is a truth state that varies.
The multiflag variable translates into I6 as "multiflag".

[A stack of multiple object lists. This allows arbitrarily nested calls to our take all phrase below.]
mol stack is a list of list of objects that varies.

[Take all as if the player had typed it.]
To take all:
	let backup mol be the multiple object list;
	parse all;
	if the multiple object list is empty:
		alter the multiple object list to backup mol;
		instead say "There are none at all available!";
	let oldflag be multiflag;
	now multiflag is true;
	add backup mol to mol stack;
	repeat with O running through the multiple object list:
		say "[O]: [run paragraph on]";
		try taking O;
	let N be the number of entries in mol stack;
	let backup mol be entry N of mol stack;
	remove entry N from mol stack;
	now multiflag is oldflag;
	alter the multiple object list to backup mol;

[Invoke "take all" programmatically via the take all phrase. The point of this whole exercise.]
Instead of jumping:
	take all.

[Test what happens when our "take all" code is triggered by an in-progress multiple action.]
After taking coin:
	say "You pick up the coin and are suddenly compelled to take everything.";
	take all;
	continue the action.

[Write a deciding whether all includes rule and make sure that it works with our take all.]
Rule for deciding whether all includes glove: it does not.

[Parse "all" as if we had typed "take all". Calls I6 code below.]
To parse all: (- ParseAll(); -).

Include (-
[ ParseAll result;
	@push indef_mode; @push indef_type; @push indef_wanted; @push indef_cases; @push action_to_be;
	indef_mode = true;
	indef_type = PLURAL_BIT;
	indef_wanted = INDEF_ALL_WANTED;
	indef_cases = $$111111111111;
	action_to_be = ##Take;
	multiple_object-->0 = 0;
	result = NounDomain(actors_location, actor, MULTI_TOKEN, true);
	! if we got a single object, stash it in multiple_objects anyway so that our take all phrase above can see it.
	if (result >= 2) {
		multiple_object-->0 = 1;
		multiple_object-->1 = result;
	}
	@pull action_to_be; @pull indef_cases; @pull indef_wanted; @pull indef_type; @pull indef_mode;
];
-).
Test me with "jump / drop all but coin / e / jump / jump / w / jump / jump / take glove / e / drop all / take all".

Edit: add stack for multiple object lists.

You can just write a “For reading a command” rule that feeds “get all” into the player’s command when a flag is set (and then unsets the flag, or there will be weeping and lamentations). Then when you want to issue the “get all,” set the flag.

[code]Lab is a room. “You can see a boompdoggle in the room description.” A rock, a cruller, a cronut, a donut, and a bownut are in Lab. A boompdoggle is scenery in Lab.

Forcing getting all is a truth state that varies.

To force getting all:
now forcing getting all is true.

For reading a command when forcing getting all is true:
change the text of the player’s command to “get all”;
now forcing getting all is false.

After jumping:
say “For some reason you are mechanically compelled to pick everything up.”;
force getting all.[/code]

And if you want to store this in a table of stored actions, just create a dummy action without any Understand statement that invokes it, and put that in the table:

[code]Lab is a room. “You can see a boompdoggle in the room description.” A rock, a cruller, a cronut, a donut, and a bownut are in Lab. A boompdoggle is scenery in Lab.

Forcing getting all is a truth state that varies.

To force getting all:
now forcing getting all is true.

For reading a command when forcing getting all is true:
change the text of the player’s command to “get all”;
now forcing getting all is false.

Mechanically picking up everything in sight is an action applying to nothing.
Carry out mechanically picking up everything in sight: Force getting all.

Table of compulsions
compulsion
taking inventory
taking the cronut
eating the cronut
dropping the cronut
mechanically picking up everything in sight

Every turn:
repeat through the table of compulsions:[in combination with the “break” command, this just gets the first row]
if there is a compulsion entry:
say “For some reason you cannot avoid [compulsion entry].”;
try the compulsion entry;
blank out the whole row;
break.[/code]

(Is there a more elegant way to just pick the first nonempty row of the table?)

Also with a bit of tinkering you should be able to make this apply to any text you want (so you could feed in “drop all” or “get the donut and the cronut”).

My goal was to make it as much like a hypothetical “try getting all” as possible, allowing additional code to come after it in the context of the original action. For example:

Before dropping something when the player encloses the noun:
	Say "You need more stuff before you'll be comfortable relinquishing [the noun]. You grab everything in sight!";
	take all;
	Say "[line break]Ok, now you're ready... [run paragraph on]".

Thanks both.

I like Matt’s changing the text approach, except I probably have no text to change. This is for single keystroke input via Glulx Unified Input in my CYOA extension.

What I’m trying to do is create a ‘get all’ option that can be made to appear automatically whenever it’s relevant. If the player chooses it, a ‘get all’ is issued.

I also want ‘get all from’ and ‘drop all’. Again, that’s why a text-changing version would have been great. It looks like I will probably have to write each one specifically and so something like what Vince has shared.

-Wade

Here’s a version that parameterizes the action. It uses the Editable Stored Actions extension by Ron Newcomb.

It defines the general phrases “apply to all” and "apply to all with indirect object ", and it also defines some convenience phrases that call them (“take all”, “drop all”, "remove all from ", etc.).

It should be relatively easy to extend it for actors other than the player if needed.

Test Chamber is a room.

Include Editable Stored Actions by Ron Newcomb.

The ball is a thing in Test Chamber.
The glove is a wearable thing in Test Chamber.
The player carries a coin.
The bucket is an open container in Test Chamber.
A rock is a kind of thing.
5 rocks are in the bucket.

A room called Other Room is east of Test Chamber.
The balloon is a thing in Other Room.
	
[ Convenience phrases for various actions. Note that if we pass in an action that doesn't take multiple objects, it will be applied to multiple objects anyway.]
To take all:
	apply taking action to all.
	
To drop all:
	apply dropping action to all.

[Paragraph breaks are a property of examine specifically.]
To examine all:
	apply examining action to all.
	
To smell all:
	apply smelling action to all.

To remove all from (T - thing):
	apply removing it from action to all with indirect object T.
	
To insert all into (T - thing):
	apply inserting it into action to all with indirect object T.

[ Shortcut for actions with no indirect object. Calls more general version below.]
To apply (name - action name) to all:
	apply name to all with indirect object nothing.

[Setting multiflag prevents paragraph breaks in between our multiple actions below.]
multiflag is a truth state that varies.
The multiflag variable translates into I6 as "multiflag".

[A stack of multiple object lists. This allows arbitrarily nested calls to our apply phrase below.]
mol stack is a list of list of objects that varies.

[Stored action variable used by our generic apply phrase below. Won't compile as a local variable.]
editable action is an action that varies.

[Debug flag that causes apply phrase to print explanatory messages when set.]
debug apply is initially true.

[Apply action to all as if the player had typed it.]
To apply (name - action name) to all with indirect object (IO - object):
	if debug apply is true:
		say "(applying [name] to all[if IO is not nothing] with iobj [IO][end if])[command clarification break]";
	let backup mol be the multiple object list;
	parse all for name with indirect object IO;
	if the multiple object list is empty:
		alter the multiple object list to backup mol;
		instead say "There are none at all available!";
	let oldflag be multiflag;
	now multiflag is true;
	add backup mol to mol stack;
	repeat with O running through the multiple object list:
		say "[O]: [run paragraph on]";
		[ We reset action fields inside the loop since it might have been changed during previous iteration.]
		change the action name part of editable action to name;
		change the noun part of editable action to O;
		change the second noun part of editable action to IO;
		try editable action;
	let N be the number of entries in mol stack;
	let backup mol be entry N of mol stack;
	remove entry N from mol stack;
	now multiflag is oldflag;
	alter the multiple object list to backup mol;

[Create some rules that apply actions to all programmatically. The point of this whole exercise.]

Instead of jumping:
	take all.

[Test nested multiple actions.]
After taking coin:
	say "You pick up the coin and are suddenly compelled to take everything.";
	take all;
	continue the action.
	
Instead of waving hands:
	drop all.

[Test a single action used as a multiple action.]
Instead of sleeping:
	smell all.
	
Instead of attacking something:
	remove all from the noun.

[Because we want to kick bucket to work.]
Understand "kick [something]" as attacking.
	
Instead of squeezing something:
	insert all into the noun.

[Write a deciding whether all includes rule and make sure that it works with our multiple actions.]
Rule for deciding whether all includes glove: it does not.

[Parse "all" for a particular action and a particular indirect object. ]
To parse all for (name - action name) with indirect object (IO - object): (- ParseAll({name}, {IO}); -)

Include (-
[ ParseAll action_name iobj  result token;
	@push indef_mode; @push indef_type; @push indef_wanted; @push indef_cases; @push action_to_be; @push advance_warning;
	indef_mode = true;
	indef_type = PLURAL_BIT;
	indef_wanted = INDEF_ALL_WANTED;
	indef_cases = $$111111111111;
	action_to_be = action_name;
	multiple_object-->0 = 0;
	advance_warning = iobj;
	switch (action_name) {
	   	##Remove: token = MULTIINSIDE_TOKEN; 
	      	##Drop: token = MULTIHELD_TOKEN;
		##Insert: token = MULTIEXCEPT_TOKEN; 
		default: token = MULTI_TOKEN;
	}
	result = NounDomain(actors_location, actor, token, true);
	! filter iobj out of multiple obj list if necessary, so we don't try to put something in or remove it from itself.
	if (result == 1) {
		ReviseMulti(iobj);
	}
	! if we got a single object, stash it in multiple_objects anyway so that our apply phrase above can see it.
	if (result >= 2) {
		print "ParseAll: result >= 2^";
		multiple_object-->0 = 1;
		multiple_object-->1 = result;
	}
	@pull advance_warning; @pull action_to_be; @pull indef_cases; @pull indef_wanted; @pull indef_type; @pull indef_mode;
];
-).

Test one with "jump / drop all but coin / e / jump / jump / w / jump / jump / take glove / e / drop all / take all".
Test two with "jump / wave / take coin / drop coin / squeeze bucket / kick bucket / drop bucket / kick bucket / sleep".

Thanks for more impressive code. I don’t know how you knock it up so fast! But I’m probably gonna try and keep my code simpler than this (and without adding an extension) unless it gets to where I need this kind of functionality more universally.

  • Wade