more bizarre output when buying multiples

My player has one torch. I want to buy three more. However, the number of torches my player ends up with varies, rather randomly. In the best case, the torch already carried by the player is ignored and not counted in the inventory tally.
Does anyone know a simple way to buy or sell multiple things? (the TAKING action works, but it is well behind the curtain.)
Here is the code and output.

The block buying rule is not listed in any rulebook.
[The item must exist in showcase and player must have enough money for it.]
Check buying something when location is Emporium:
	if the noun is in a showcase (called S) in the Emporium:
		now the currentCase is S;
		let C be ChrCostBuying for cost of noun;
		if C > moneyAmt of cash:
			say "That [noun] costs [C to 1 decimal places] gp.";
			say "You don't have enough money" instead;
	otherwise:
		say "Ganon shakes his head and says, 'Sorry, I don't have any more. Perhaps I'll get some in later.' " instead;
			
Carry out buying when location is Emporium:
	let C be ChrCostBuying for cost of noun;
	decrease moneyAmt of cash by C;
	now player is carrying the noun;
	say "Ganon takes your [C to 1 decimal places] gp, then removes the [noun] from the [currentCase] and hands it to you.";
	say " '[one of]Excellent choice![or]You've made a fine decision,[or]That should serve you well,'[at random][run paragraph on] he says.";

[BULK-BUYING ACTION]
Bulk-buying is an action applying to one thing.
Understand "buy [things]" as bulk-buying.

The can't take what's already taken rule is not listed in any rulebook.

Carry out bulk-buying:
	let Q be the number of entries in the multiple object list;
	if the noun is in a showcase (called S) in the Emporium:
		say "[noun] is in the [S] showcase[line break]";
	repeat with N running through multiple object list:
		try buying noun instead;

This seems overdone.

It seems that the first item in the multiple object list is empty, or treated as not found. The other two BUY actions work, thus giving the player 3 torches: 2 bought an 1 previously carried.

Since your Understand line for bulk-buying says simply [things], and you haven’t made it unlikely to bulk-buy something you’re already carrying, Inform just picks any three torches the player can see—potentially including one already in their hands.

1 Like

Oh, I forgot to include a line that is in my code, but not in the post:

[To force search to start with showcases.]
Does the player mean buying something which is enclosed by a showcase:
	it is very likely.

That buys only in the showcases.
Do I need to say something like

Does the player mean bulk-buying something which is enclosed by a showcase:
	it is very likely.

That only applies to buying, though, not bulk-buying.

I don’t really see why bulk-buying is needed here. Why not just Understand “buy [things]” as buying?

2 Likes

Oh, gosh! I can’t believe that worked! And that I didn’t think of it. :man_facepalming:
I will try to deal with multiple item costs and see if there are any side effects.

1 Like

I am getting looping output that doesn’t make sense, or at least is annoying.
I thought that perhaps I could clear the multiple object list so that contains nothing, as in let L be the multiple object list; ... alter L to { };
but that get a compile error.
Is there any easy way to turn of the output from, in this case, the BUY action?
Here is how it looks now

Does silent try work?

silently try buying noun instead;

Good idea but I had to change the code (for other reasons) to not call the buying action. Here is what I have now. Where do I put the “silently” phrase? It works except for the output trail.

Check buying something when location is Emporium:
	if the noun is in a showcase (called S) in the Emporium:
		now the currentCase is S;
		let C be ChrCostBuying for cost of noun;
		if C > moneyAmt of cash:
			say "That [noun] costs [C to 1 decimal places] gp.";
			say "You don't have enough money" instead;
	otherwise:
		say "Ganon shakes his head and says, 'Sorry, I don't have any more. Perhaps I'll get some in later.' " instead;
			
Carry out buying when location is Emporium:
	let Q be number of entries in multiple object list;
	if Q is 0:			[Q is 0 for only one entry]
		now Q is 1;
	let C be (ChrCostBuying for cost of noun) * Q;
	decrease moneyAmt of cash by C;
	now player is carrying the noun;
	say "Ganon takes your [C to 1 decimal places] gp, then removes the [noun] from the [currentCase] and hands it to you.";
	say " '[one of]Excellent choice![or]You've made a fine decision[or]That should serve you well[at random][run paragraph on],' he says.";

If the issue you’re having is that the player tries to buy each of these things individually as separate actions, then yeah that’s standard for any action with a “[things]” token. It’s how I7 handles bulk-commands.

The following is a little limited (the way I’ve written it, you can only buy one kind of thing at once), but it should let players buy mass numbers of things without having to deal with all of those repeating messages, since you seem to not be fond of them.

currentCase is an object that varies.

A thing has a number called cost.
A thing has a number called bulk-identifier.

A showcase is a kind of container.
A torch is a kind of thing. The cost of a torch is usually 1. The bulk-identifier of an torch is usually 1. There are 12 torches.
An arrow is a kind of thing. The cost of an arrow is usually 1. The bulk-identifier of an arrow is usually 2. There are 3 arrows.

Definition: a thing is locationShowcased if it is in a showcase in the location.

When play begins:
	repeat with item running through torches:
		now item is in the goods showcase;
	repeat with item running through arrows:
		now item is in the goods showcase;
		

The Emporium is a room. Ganon is a person in the Emporium. The goods showcase is a showcase in the emporium.
The Garden is south of the Emporium.

This is the my announce items from multiple object lists rule:
	if the current action is not buying and the current item from the multiple object list is not nothing,
		say "[current item from the multiple object list]: [run paragraph on]" (A).

The my announce items from multiple object lists rule is listed instead of the announce items from multiple object lists rule in the action-processing rules.

Understand "buy [things]" as buying.

Does the player mean buying a carried thing: it is unlikely.

The buying action has a number called goods quantity.
The buying action has a list of things called goods bought.
The buying action has a number called good type bought.
The buying action has a truth state called too many types.

Rule for setting action variables for buying (this is the bulk buying rule):
	now good type bought is the bulk-identifier of the noun;
	if the number of entries in the multiple object list is greater than 1:
		let Count be 0;
		repeat with item running through the multiple object list:
			if the bulk-identifier of the item is the good type bought:
				if the item is locationShowcased:
					if Count is 0:
						now the noun is the item;	[We don't need the original noun for much, just in case it's carried. Let's make the noun something we ***know***.]
					increment Count;
					add item to goods bought;
			else:
				now too many types is true;
				break;
		now goods quantity is count;
	if goods quantity is less than 2:	
		now goods quantity is 1;
	alter the multiple object list to { };

The block buying rule is not listed in any rulebook.
First check buying something when location is emporium (this is the please simplify bulk buying rule):
	if too many types is true:
		say "Ganon briefly glances about for a pen and paper. Maybe you should stick to one kind of purchase at a time?";
		stop the action;
		
Check buying:
	if a showcase is not in the location:
		say "There's nothing to buy out here.";
		stop the action;

Check buying something when location is Emporium (this is the deny buying from an empty showcase rule):	
	if the noun is in a showcase (called S) in the Emporium:	[Remember! We set a proper noun for bulk buying earlier.]
		now the currentCase is S;
	otherwise:
		say "Ganon shakes his head and says, 'Sorry, I don't have any more. Perhaps I'll get some in later.'" instead;
			
Carry out buying when location is Emporium (this is the pay-less let player buy in the emporium rule):
	if goods quantity is greater than 1:
		repeat with item running through goods bought:
			now the player is carrying item;
	else:
		now player is carrying the noun;
	
Report buying when location is Emporium (this is the report buying rule):
	let C be (the cost of the noun * goods quantity);
	say "Ganon takes your [C to 1 decimal places] gp, then removes [if goods quantity is less than 2]the [noun] from the [currentCase] and hands it to you[else][goods quantity in words] [printed plural name of the noun] from the [currentCase] and hands them to you[end if].[run paragraph on]";
	say " '[one of]Excellent choice![run paragraph on][or]You've made a fine decision,[or]That should serve you well,'[at random][run paragraph on] he says.[line break][line break]";
	rule succeeds;
	
Every turn:
	now currentCase is nothing;

Emporium
You can see Ganon and a goods showcase (in which are three arrows and twelve torches) here.

>buy arrow
Ganon takes your 1.0 gp, then removes the arrow from the goods showcase and hands it to you. "Excellent choice! he says.

>buy arrow and torch
Ganon briefly glances about for a pen and paper. Maybe you should stick to one kind of purchase at a time?

>buy 3 arrows
Ganon takes your 2.0 gp, then removes two arrows from the goods showcase and hands them to you. “That should serve you well,” he says.

>buy arrows
Ganon shakes his head and says, “Sorry, I don’t have any more. Perhaps I’ll get some in later.”

>buy three torches
Ganon takes your 3.0 gp, then removes three torches from the goods showcase and hands them to you. "Excellent choice! he says.

>buy torches
Ganon takes your 9.0 gp, then removes nine torches from the goods showcase and hands them to you. "You’ve made a fine decision, he says.

>inventory
You are carrying:
twelve torches
three arrows

>s

Garden

>buy torches
There’s nothing to buy out here.

I’ve had to gut the mechanisms here a bit since I once again don’t have access to all of your variables and tables, but this should be a semi-scaleable skeleton which checks local showcases for contents matching the kind of noun (as classified by its bulk identifier) and buys all of the ones available.

If the player tries to buy more than one thing at once it tells the player to simplify things, though I can think of ways to get even that workable if you want to put the time in.

As a warning, since this is still technically part of multiple object processing you’ll need to get aggressive with some line breaks (note my own double line break at the bottom there) for your report rules. The automatic mechanisms choke up a little when you override them like this.

But yes! Hope this can help.

Edit: Apologies! Forgot to include my output, and made a slight edit to the response text.

1 Like

I have the mechanisms working fine (without creating a bulk-buying action; thank you Draconis) except for one annoying detail. Because the BUY 3 torches command is repeatedly called 3 times, the REPORT BUYING is also called three times, so my summary statement is repeated three times, giving the wrong information.

The block buying rule is not listed in any rulebook.
The can't take what's already taken rule is not listed in any rulebook.
The announce items from multiple object lists rule is not listed in any rulebook.

[Needed for data between carry out and reporting activity.]
BulkCost is a real number that varies. 

[The item must exist in showcase and player must have enough money for it.]
Check buying something when location is Emporium:	
	now BulkCost is 0.0;
	let Q be the number of entries in multiple object list;
	if Q is 0:			[single item is 0 in multiple object list]
		now Q is 1;
	if the noun is in a showcase (called S) in the Emporium:
		now the currentCase is S;
		now BulkCost is (ChrCostBuying for cost of noun) * Q;
		if BulkCost > moneyAmt of cash:
			say "Those [printed name of noun] costs [BulkCost to 1 decimal places].";
			say "You don't have enough money." instead;
	otherwise:
		say "Ganon shakes his head and says, 'Sorry, I don't have any more. Perhaps I'll get some in later.' " instead;
			
Carry out buying when location is Emporium:
	let C be ChrCostBuying for cost of noun	;
	decrease moneyAmt of cash by C;
	now player is carrying the noun;
	
[This should only print once for bulk buying.]
Report buying:
	say "Ganon takes your [BulkCost to 1 decimal places] gp, then removes the [noun] from the [currentCase] and hands it to you.";
	say "[one of]'Excellent choice!'[or]'You've made a fine decision.'[or]'That should serve you well.'[at random]" instead;

with the output

I expected that the carry out code would be called three times, but not the REPORT BUYING activity. Is there a way to turn off the reporting after the first time? I’ve already turned off the 'announce items from multiple object lists rule is not listed in any rulebook".
Not sure what problems that may cause later, but I’ll cross that bridge…

By default? No. But…

To globally silence:
	(- (keep_silent = true) -);
To globally unsilence:
	(- (keep_silent = false) -);
	
Understand "buy [things]" as buying.
	
The block buying rule is not listed in any rulebook.
The can't take what's already taken rule is not listed in any rulebook.
The announce items from multiple object lists rule is not listed in any rulebook.
			
Carry out buying:
	now player is carrying the noun;
	
[This should only print once for bulk buying.]
Report buying:
	say "Ganon takes your <whatever number> gp, then removes the [noun] from the <whatever case> and hands it to you.";
	say "[one of]'Excellent choice!'[or]'You've made a fine decision.'[or]'That should serve you well.'[at random][line break]";
	globally silence;
	rule succeeds;
	
Every turn:
	Globally unsilence;
	
An apple is a kind of thing. There are 3 apples.
	
The Emporium is a room.

When play begins:
	repeat with item running through apples:
		now item is in the Emporium.

The problem with this is that if you invoke “trying silently” I’m pretty sure that this global silence setting will be wiped, which could lead to unpredictable results. I personally recommend trying to properly condense it all into one action if you’re insistent on the output situation (partially because delisting announcing multiple objects itself can cause issues when the player inevitably tries to “take all”), but yeah this can shut up any subsequent report rulebooks until the next turn occurs.

Edit:

This is the my announce items from multiple object lists rule:
	if the current action is not buying and the current item from the multiple object list is not nothing,
		say "[current item from the multiple object list]: [run paragraph on]" (A).

The my announce items from multiple object lists rule is listed instead of the announce items from multiple object lists rule in the action-processing rules.

(For the record, this excerpt from my earlier code might help make your life a bit easier when it comes to the multiple object list. It would leave other actions intact and just apply this behaviour to buying.)

1 Like

Trying silently should be all right; action processing generally pushes keep_silent onto the stack at the beginning, then pops it back off at the end, so it’ll remember the original state of the flag. The default rules allow any action to set it, but not to clear it, so all children of a silent action will also be silent.

2 Likes

Ah! Apologies, just tested it and Daniel is correct. This “globally silence” I threw together is less testy than I’d remembered.

1 Like

Great! I was hoping for something like this, a focused error message removal than one for all events.

I think I have another way of turning off the output for just this situation, using a blocal variable. I’ll let you know how it turns out.

I didn’t want to deal with I6 and global issues, but I got this code working for bulk buying and loop control.

BulkCounter is a number that varies. 	[Control multiple object llist looping.]

Before buying something when location is Emporium:
	if BulkCounter is 0:
		now BulkCounter is the number of entries in multiple object list;
Report buying:
	decrement BulkCounter;
	if BulkCounter is 0:
		say "Ganon takes your [BulkCost to 1 decimal places] gp, then removes the [noun] from the [currentCase] and hands it to you.";
		say "[one of]'Excellent choice!'[or]'You've made a fine decision.'[or]'That should serve you well.'[at random]" instead;

Now only the last time through the multiple object list does the report sayings get output.

The “Check buying” and “Carry out buying” works the same as before.

Bringing this discussion back here for a moment, I thought I might want to bring this up in case there’s some undesireable behaviour. Perhaps I’m just not seeing all of the safety checks you’ve included. I’ve been trying to piece together your code from the snippets you’ve shared. That being said…

currentCase is an object that varies.
BulkCost is a real number that varies.
BulkCounter is a number that varies.

A thing has a number called cost.

A showcase is a kind of container. An arrow is a kind of thing. The cost of an arrow is usually 1. A torch is a kind of thing. The cost of a torch is usually 2.
There are 5 arrows. There are two torches.

The Emporium is a room. The goods showcase is a showcase in the Emporium. Ganon is a person in the Emporium.

[=======]

This is the my announce items from multiple object lists rule:
	if the current action is not buying and the current item from the multiple object list is not nothing,
		say "[current item from the multiple object list]: [run paragraph on]" (A).

The my announce items from multiple object lists rule is listed instead of the announce items from multiple object lists rule in the action-processing rules.

Understand "buy [things]" as buying.
The block buying rule is not listed in any rulebook.

Check buying something when location is Emporium:	
	now BulkCost is 0.0;
	let Q be the number of entries in multiple object list;
	if Q is 0:
		now Q is 1;
	if BulkCounter is 0:
		now BulkCounter is Q;
	if the noun is in a showcase (called S) in the Emporium:
		now the currentCase is S;
		now BulkCost is (the cost of the noun) * Q;
	otherwise:
		say "Ganon shakes his head and says, 'Sorry, I don't have any more. Perhaps I'll get some in later.' " instead;
			
Carry out buying when location is Emporium:
	let C be the cost of the noun;
	now player is carrying the noun;
	
Report buying:
	if BulkCounter is 1:
		say "Ganon takes your [BulkCost to 1 decimal places] gp, then removes the [noun] from the [currentCase] and hands it to you.";
		say "[one of]'Excellent choice!'[or]'You've made a fine decision.'[or]'That should serve you well.'[at random]" instead;
	decrement BulkCounter;
	
When play begins:
	repeat with item running through arrows:
		now item is in the goods showcase;
	repeat with item running through torches:
		now item is in the goods showcase;
		
Every turn:
	now the currentCase is nothing;
	now the BulkCost is 0;

Once again, I might genuinely just be missing a piece of the puzzle. As far as I can tell, though, trying to buy multiple types of things still has you buy them but only provide report text for the absolute last thing on the list.

1 Like