I have tables with the names of things that exist in nowhere. The player asks for one of those things like “buy sword”. In that case, sword should be moved from nowhere to the player’s location for manipulation, but “sword” is text and Inform doesn’t associate it with an object. How can I match the text with the object? The parser does this behind the scenes (as by using an action BUYING with SWORD as the noun). How can I do that as an author?
Doesn’t the parser already associate the name as “describing the object?”
A thing can be purchasable. A thing is usually not purchasable.
The sword is purchasable.
Purchasing is an action applying to one purchasable thing. Understand "purchase [something]" and "buy [something]" as purchasing.
And then you can move the noun
to the player’s inventory and remove the appropriate amount of money.
Lab is a room.
The worldview is a privately-named backdrop.
The worldview is everywhere.
VirtualShop is a privately-named opaque open container.
VirtualShop is part of the worldview.
A sword is a thing.
A sword is in VirtualShop.
The printed name of a sword is "sword".
Understand the printed name property as describing a thing.
Understand the command "buy" as something new.
Understand "buy [any thing]" as purchasing.
Purchasing is an action applying to one thing.
Rule for deciding the scope of the player while purchasing:
repeat with LocalThing running through things which are in VirtualShop:
place LocalThing in scope.
Carry out purchasing:
let the target be the noun;
if the target is in VirtualShop:
move the target to the location of the player;
say "You have bought [the target].";
otherwise:
say "You can't buy that here.";
Lab
>buy sword
You have bought the sword.
>look
Lab
You can see a sword here.
>
I can’t manage it on my end with nowhere, but my control freak side prefers recycling objects in compartmentalized private rooms. In this specific case, using a private backdrop that is not known to the players seems like a good option to me.
During gameplay, the parser is resistant to understanding typed text as referring to entities that aren’t immediately accessible to the player. (Even if only one object has the internal name sword
, in practice the typed text “sword” might refer to any number of things, and the first rule the parser uses to narrow down the question “which one does the player mean?” is “well, which ones are physically present?”)
There are lots of ways around this, but I think the most “Informian” approach is to have the shop’s wares not be offstage, but present in the shop location.* Then you don’t have to add new actions or fiddle with scope; you should be able to handle things the “native” way as they are in the Recipe Book examples (especially “Frozen Assets,” which makes the whole thing look super easy).
*Consider that in the solutions offered above, you’d still have to do some extra work to prevent the player from buying things while the player isn’t in the shop!
You may be looking for “applying to one visible thing,” which may seem counterintuitive, since it isn’t visible to you at the moment. But that’s how Inform rolls. “applying to one thing” is only stuff you can see.
That is true. So we can write something like:
VirtualShop-backdrop is a privately-named backdrop.
VirtualShop-backdrop is everywhere.
VirtualShop is a privately-named opaque open container.
VirtualShop is part of VirtualShop-backdrop.
When play begins:
move the VirtualShop-backdrop backdrop to all rooms which are shops;
EDIT : “full” code below:
Lab is a room.
A shop is a kind of room.
East of Lab is The Inn.
The inn is a shop.
VirtualShop-backdrop is a privately-named backdrop.
VirtualShop-backdrop is everywhere.
VirtualShop is a privately-named opaque open container.
VirtualShop is part of VirtualShop-backdrop.
When play begins:
move the VirtualShop-backdrop backdrop to all rooms which are shops;
A sword is a thing.
A sword is in VirtualShop.
The printed name of a sword is "sword".
Understand the printed name property as describing a thing.
Understand the command "buy" as something new.
Understand "buy [any thing]" as purchasing.
Purchasing is an action applying to one thing.
Rule for deciding the scope of the player while purchasing:
repeat with LocalThing running through things which are in VirtualShop:
place LocalThing in scope.
Carry out purchasing:
let the target be the noun;
if the target is in VirtualShop:
move the target to the location of the player;
say "You have bought [the target].";
otherwise:
say "You can't buy that here.";
Lab
>buy sword
That isn't available.
>e
The Inn
>buy sword
You have bought the sword.
I guess the corresponding code for my suggestion would be
Street is a room.
Shop is east from Street.
The sword is in Shop.
Carry out buying the sword:
say "You purchase the sword.";
now player carries the sword;
…without getting into the specifics of how much money you have, how much the sword costs, or blocking >TAKE SWORD without paying for it, etc.
I vaguely remember in another thread discussing putting the shop’s wares inside a transparent closed unopenable container. I think this would let them be seen and examined but not taken.
Assuming you have more than one shop you could also say something like
A room can be commercial. A room is usually not commercial.
Check buying:
unless the location is commercial:
say "Nobody is selling anything here." instead.
Though if you have a traveling salesperson or similar things get more complicated.
My problem is that the noun is text, and noun is not recognized by Inform. How can I take text to the noun that already exists?
This is exactly what scope is for, though. Matching player input against a different set of objects than the default “what the player can see in the room”.
Thanks. This is good to know about how the parser interprets text. That should move me toward a solution, but there are two reasons I can’t put all the wares into the shop:
(1) I want multiples of many things. The player can buy a sword in many places, and he/she can buy 5 swords, which are really only a single thing. I use a number property and “printed name of” to hide this from the player.
(2) There are dozens of items and I don’t want them all to display in the location. When I tried grouping them, it took the items being carried from the player. When I tried scenery, then I couldn’t manipulate them. That approach also interfered with Item (1).
Is there any particular reason why you aren’t using duplicates (WWI 4.14) ?
Thank you. That is interesting. I am not having trouble building actions though (I have quite a few) but when an NPC asks something like “What do you want appraised?” the player replies, “sword”, Inform can’t recognize the sword object from the text answer “sword”. I think Ryan explained why not, and Stephane provided the code I should try.
I think this is the code I need. Understand the printed name property as describing a thing.
and use a room instead of nowhere. I didn’t realize that nowhere had the special identity. I’ll try something like VirtualSpace (the same item can appear in multiple locations). Ryan’s tip about how the parser associates input text with objects was helpful too.
Yes, that is why I chose nowhere. I didn’t realize it didn’t work the same as a private room out of play.
Yes, I have that covered in the Check phrase of my action. The target object must always be in the same location as the player to buy, appraising, selling, etc. to work. The name is checked against a table of items available and then the object is transferred from VirtualSpace into the location. My problem was converting the text name to the object I needed.
I couldn’t get multiples to work. If I say two swords are in the shop, Inform understood that as the name of a single object “two swords”. Since Inform can’t create objects on the fly, I would have hundreds of objects statically created and I couldn’t think of how to differentiate them. I choose to keep a single unique object with Quantity property; actually I create two objects, one for carrying and one for manipulation within the location or stored in VirtualSpace.
It is a common requirement that a player can (for example) buy 25 arrows from more than one location; or sell multiple gems.
Maybe you will be interested in the last 5 or 6 posts in this thread. The same line of code saved my WIP. Because if you deal with a great number of items or monsters or extras-NPC, it’s cool to control memory use while recycling things. With only a dozen passersby, some tables to make them suitables for a decent city and a cycling routine, you can set up a place with hundreds of transient citizens.
OK understood. Thanks for explaining.
Yes, that thread was useful, but using the printed name property didn’t work.
I define a table of things and display them. As part of display, I move the item into the player’s location, which in this case is Ganon’s Emporium. Here is the code, trimmed slightly.
[General rule to display Ganon's inventory lists.]
To display (title - text) inventory from (tbl - table name):
say "[line break][bold type][line break] [title][line break]";
build colhdrs from tbl;
repeat through the tbl:
now nbr entry is the qty of item entry;
say "[fixed letter spacing][item entry] [nbr entry] [price] [weight entry]";
now item is in player's location;
say "[variable letter spacing][paragraph break]";
The item starts off in nowhere (by default) and (should) move into the player’s location. Everything had been working fine until I put that line in. Do you think it is because the object started in nowhere, instead of Virtual Space?
Perhaps this is a better example: associating names with objects.
[code] [Define Equipment as my major manipulation kind.]
Equipment is a kind of thing.
Equipment has a real number called cost.
Equipment has a real number called weight.
Equipment has a number called qty. Qty is initially 1.
Understand the printed name property as describing Equipment.
This is the appraPrep rule:
say “Ganon asks, ‘Do you have the [APPRAISAL_FEE] gp fee?’ [line break]”;
say “You check your pouch and find [cash].[line break]”;
if player consents:
now current question is “”;
now current prompt is "Ganon asks, ‘What do you want to appraise?’ ";
now punctuation removal is true;
ask an open question, in text mode;
otherwise:
say " ‘Well, okay, but don’t forget about me when you do.’ ";
A text question rule (this is the getAppraise_Item rule):
let myItem be current answer;
say “[advName of player] holds out [pron of player] [myItem].”;
showme myItem;
now myItem is in player’s location;
exit;
[/code]
Everything works fine until I add the line “now myItem is in player’s location.” The parser objects that myItem is text (as the showme MyItem statement confirms) and won’t bring in the object. ??