Selecting Tarot Cards [merged thread]

I’m already going to give coding credit to all of those who have helped me in this story. My (alpha) journey is at an end, I am at the final, meta-puzzle.

Basically, the player will need to pick the correct tarot card from one of three cards. There are about 35 series of 3 cards that will be offered. The player will need to pick the correct one from each of these in order to win (how the player does this, I’m keeping a secret).

In each series, 2 of the 3 cards need to be randomly chosen from the tarot deck. This way, the confusing stimuli changes every time. The three cards in each series also need to be randomly arranged each time they are dealt.

Here’s an example: the first series of cards has the 2 of wands that the player needs to pick. The two random cards in this case are the Hierophant and the 7 of swords. They need to be arranged in a random order (in this case, Hierophant, 2 of wands, 7 of swords) and the player needs to pick the 2 of wands to move on to the next series.

I had hoped that by the time I got to the point I would have the coding experience to do this. But what I envision is incredibly inefficient in terms of coding. Any hints, even just a push would help.

Thank you in advance for your thoughts!

1 Like

Apologies if I’m missing something - in what program/language are you writing this game?

Not sure what you’re writing this in, but i would make two card lists; correct-cards and incorrect-cards. sort both randomly, then for each series, take the next correct-card and the next two from incorrect-cards.

1 Like

Sorry, it’s Inform.

1 Like

This is Inform 7/10, like your other posts, right? I don’t have time right now to write up a full implementation (I’m sure others will be along to do that soon!) but in case it’s helpful to sketch out an approach:

-I’d create “cards” as a kind and define the specific ones via a table, as in this example involving jerseys.

-Then I’d create a list of the three thirty-six “right” cards (sorry, misread your post), blanking out the rows from the table as they’re chosen (see docs link in next bullet point).

-Then at each choice point, I’d create a new list made from the Nth element of that list and choose two more at random from the table (blanking out the row each time so the same card can’t be drawn more than once). See these two bits of the doc for that.

-Then just sort that list in random order and present it to the player (I’m assuming you have a system for displaying and picking cards - that should be pretty straightforward!)

3 Likes

If you’re planning to draw from the whole deck, I’d probably start with a table. A row per card. Have a specific field update once the card is dealt.

Or nuke the row, if there’s no need to recall dealt cards

Doing what Mike says is a good idea.

1 Like

Are the correct cards a list of 35 cards that’s defined before the player begins choosing? Or will you be dynamically selecting what the upcoming correct card is just before presenting the player with the three cards? or other?

Yes, the 36 cards (I actually just counted them) are predetermined for each row. The entire puzzle is a distractor and the answer is really simple as to which ones to choose.

I’d do everything Mike said. Additionally, create either a list or a second table for your correct cards. When the game starts (or whenever you select the 36 correct cards), delete the corresponding rows from the first table and add them to the list-or-second-table.

As you present choices, remove them from the list-or-second-table.

After each choice, you’ll want to add the two incorrect cards back to the original table, or you’d run out of cards before you’re done.

1 Like

Are the incorrect cards drawn from the same deck as the correct ones? (So can the correct answer for one row turn up as a wrong option in another row?)

I’m gonna do it myself! For fun!

A tarot card is a kind of thing.

But it’s not fun to type out the names of all the tarot cards so I’m going to write some code to do that for me.

Suits is initially { "Swords", "Cups", "Pentacles", "Wands" }.

Ranks is initially { "Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Page", "Knight", "Queen", "King" }.

When play begins:
	repeat with oursuit running through Suits:
		repeat with ourrank running through Ranks:
			say "The [ourrank] of [oursuit] is a tarot card.[paragraph break]"

I run the game, and I get: “The Ace of Swords is a tarot card. The Two of Swords is a tarot card. The Three of Swords is a tarot card.” and so on. I copy that into my project. I comment out the code-generating code.

But I do have to type all the major arcana myself. GROAN.

When that’s done, I can start worrying about which card is correct:

The correct card is a tarot card that varies.

Definition: A tarot card is incorrect if it is not the correct card.

I’m going to make the list of correct answers into a table.

Table of Correct Tarot Cards
usedyet	card
false	Four of Pentacles
false	XI Strength
false	XV The Devil

The “usedyet” column will track whether we’ve covered that card yet. (Frequently examples in the documentation will have you “blank out the whole row” when you’re done with a row, but this way makes it easier to reset things later.)

(It would make a whole lot of sense for this table to include a column for whatever question the player is supposed to answer by picking the correct card, or however that works. But I don’t know what’s actually going on in this puzzle.)

This next rule will run through the above table and set the “correct card” to the first row it sees that isn’t “usedyet.”

To assign the next correct card:
	let cardpicked be false;
	repeat through Table of Correct Tarot Cards:
		if cardpicked is false:
			if usedyet entry is false:
				now usedyet entry is true;
				now cardpicked is true;
				now the correct card is card entry;
				present a tarot challenge;
	if cardpicked is false:
		say "'That's all the correct cards, so I guess you win!'";
		end the story;

If “cardpicked” is still false after going through all the rows, then all the correct cards must have been used, so there’s nothing left to do! You picked all the right cards! (The reason this is included in the “assign the next correct card” rule is because we’re going to end up calling this rule after the player picks any card—even the final one.)

“Presenting a tarot challenge” is its own rule:

To present a tarot challenge:
	repeat with leftovercard running through tarot cards enclosed by the location:
		remove leftovercard from play;
	let layout be a list of tarot cards;
	add the correct card to layout;
	let badcard1 be a random incorrect tarot card;
	add badcard1 to layout;
	let badcard2 be a random incorrect tarot card;
	add badcard2 to layout;
	sort layout in random order;
	repeat with newcard running through layout:
		now newcard is in the location;
	say "Madam Sosostris places [the list of visible tarot cards] before you and tells you to pick the right one."

First we remove any cards from the previous challenge.

Then we make a list of three cards. The first entry will be the correct card. The other two entries will be incorrect cards. But when you add them to the “layout” list in this order, the first card is always the correct one, so you need to “shuffle” the list by sorting it in random order.

Then we put the cards in front of the player, and then we report to the player what cards are available. Now the ball is in the player’s court.

“Pick” isn’t a default verb, but I think it makes perfect sense to treat it as a kind of “taking” here:

Understand "pick [something]" as taking.

When you take a card, all we care about is whether it’s the correct one or not:

Instead of taking a tarot card:
	if the noun is the correct card:
		say "'That's correct!' says Madam Sosostris. ";
		assign the next correct card;
	otherwise:
		say "'That's incorrect!' says Madam Sosostris. Am I spelling that right? Anyway, you have to start over.[paragraph break]";
		repeat through Table of Correct Tarot Cards:
			now usedyet entry is false;
		assign the next correct card;

The loop for picking the right card is probably pretty obvious. When you pick the wrong card, I decided to be merciful and start the challenge over instead of hitting you with a Game Over. By going through the Table of Correct Tarot Cards and changing all the “usedyet” entries to false, we have reset your progress in the puzzle, and “assign the next correct card” will pick out the very first card in the table.

You have to assign the “next” correct card to get this all started in the first place, so for purposes of this example I included:

When play begins:
	assign the next correct card;

I have attached the source for you to mess with, to make it work the way you want: Tarot Challenge Ultimate Edition.txt (5.0 KB)

16 Likes

Yes, that’s correct.

Thank you so much for your support! The coding I would have done would have taken two or three times the space and probably several weeks! I appreciate it!

5 Likes

No problem. It was fun! Good luck with all the other parts of your game!

5 Likes

My system for displaying and picking cards isn’t working. Is there wording you could suggest?

1 Like

Hi, Ryan:

I returned again to your code – I missed a few obvious things in it that I didn’t key. So now it compiles. But my question is this – how do I “start” your code? I have the below written but when I try to present the challenge or choose the correct card all I get is a prompt:

say "The gypsy flips over one card and announces, '[bold type]The fool[roman type] begins the journey.";
		pause the game;
		clear the screen;
		say "The gypsy shuffles the desk and flips over one card and announces, '[bold type]The Fool[roman type] shows the way.'";
		pause the game;
		clear the screen;
		present a tarot challenge;

The code begins in the middle of interacting with the gypsy, as you can read. I trimmed off the entire code to just its relevant part. But how do I “start” present a tarot challenge?

1 Like

What you’ve got should work, assuming that you pasted in the “to present a tarot challenge” rule - that should get you a regular command prompt where you pick one of the three visible cards. Note that in Ryan’s code, the “to assign the next correct card” rule runs as soon as play begins (and that rule will automatically present a challenge) so if you’re starting the challenge like this, you’ll need to make sure the correct card variable has already been set for it to work properly.

2 Likes

Yes, it certainly compiles but it doesn’t start. It does not execute the “when play begins” text and, when that is removed, it doesn’t execute when the game arrives at the next in the natural course of the game.

1 Like

Huh, it works for me when I just paste in the text file Ryan posted - the text where the fortune teller presents the cards shows up before the game title blurb because the order of operations is a little messy when you use a when play begins rule, but it shows the cards and works correctly when I pick the correct one, with another choice offered in turn. Regardless, so long as you haven’t changed the text of the two main rules, it should all work so long as some rule somewhere kicks off the sequence with “assign the next correct card” since that will also automatically launch the challenge.

2 Likes

I think I didn’t name my rules in the clearest, helpfulest way. The “assign the next correct card” process must take place before the challenge begins, which doesn’t really make sense, and the “present a tarot challenge” routine should only be called as part of “assigning the next card.” Based on the names of the rules, it really feels like it should be the other way around.

I’m going to change some stuff, leave some stuff unchanged, and attach a new version.

First of all, instead of starting this “when play begins,” I’ll create a more realistic trigger (looking at Madam Sosostris), which should be simple to replace with the corresponding trigger in your game.

Madam Sosostris is a woman in Hall of Cards.

Instead of examining Madam Sosostris:
	if a tarot card is visible [the challenge is already underway]:
		say "'Don't look at me,' Madam Sosostris tells you. 'Pick the right card!'";
	otherwise [if there are no tarot cards laid out, we apparently haven't started playing]:
		say "'Time to begin the challenge!' says Madam Sosostris.[paragraph break]";
		execute a tarot choice.

“Execute a tarot choice” will be the process of Madam Sosostris determining what the next correct card should be and laying out those cards in front of you.

To execute a tarot choice:
	determine the correct card;
	lay out three cards.

When I format a rule like this, consisting of nothing but other rules that I have to define separately, it’s just to help organize the process for my own benefit. This is especially helpful when I don’t know specifically what each part of the process will entail—like, if I hadn’t yet written any code for “laying out three cards,” I would still know that it has to happen after I determine which card is the correct one. So I can get the order of operations right before I start figuring out the details.

This also makes it possible to “determine the correct card” or “lay out three cards” as an independent process. But I almost never do that kind of thing! And in this particular case, I can’t see why I would want to. So, we’re not going to write any rules that call the “determine the correct card” or “lay out three cards” rules separately from each other. We’re just going to use “execute a tarot choice” to carry out the whole process.

HOLD ON, GO BACK. As I’m writing this, I’m realizing that this “execute a tarot choice” rule is actually the place where we want to check whether you’ve completed the challenge. Do it like this instead:

Cardpicked is initially false.
		
To execute a tarot choice:
	determine the correct card;
	if cardpicked is true [we must have found the next card]:
		lay out three cards;
	otherwise [there must be no cards left to pick]:
		end the tarot challenge successfully.

The cardpicked truth state has been placed outside of a rule so that we can refer to it in multiple rules. It was a “temporary variable” before, and now it is a “global variable.” We’ll use it to mark whether we’ve picked a card during the determine the correct card routine. If, after that routine, we’ve picked a card, then it’s okay to lay out some card for the player to pick one. Otherwise, there must be no unpicked cards left in the Table of Correct Tarot Cards, so it must be the end of the game! We’ll get to that later.

ANYWAY, let’s define those steps I was talking about.

To determine the correct card:
	now cardpicked is false;
	repeat through Table of Correct Tarot Cards:
		if cardpicked is false:
			if usedyet entry is false:
				now usedyet entry is true;
				now cardpicked is true;
				now the correct card is card entry;

This is almost identical to the “assign the next correct card” rule I wrote before! There are only a few changes:

First, we have to set cardpicked to false, because now that it’s a global variable, it might have been set to “true” during a previous execution of this rule, and we need it to be false whenever we run it again.

Second, present a tarot challenge is no longer part of the rule, because we’re going to do that stuff in the lay out three cards step.

Third, the branch if cardpicked is false is gone, because that’s now handled in the to execute a tarot choice rule.

Here’s what lay out three cards looks like:

To lay out three cards:
	repeat with leftovercard running through tarot cards enclosed by the location:
		remove leftovercard from play;
	let layout be a list of tarot cards;
	add the correct card to layout;
	let badcard1 be a random incorrect tarot card;
	add badcard1 to layout;
	let badcard2 be a random incorrect tarot card;
	add badcard2 to layout;
	sort layout in random order;
	repeat with newcard running through layout:
		now newcard is in the location;
	say "Madam Sosostris places [the list of visible tarot cards] before you and tells you to pick the right one."

This is EXACTLY the same as present a tarot challenge from before. I just changed the name to better describe what the rule handles.

Digression Corner

I’d like to address some issues raised in this thread.

Defining all 76 cards as things

If you just copy and paste the code out of the .txt attached to my earlier post (or this one), that work has been done for you. I recommend treating each card as a separate object, because, the work has been done for you, for one thing. And it’s easier (and safer) than changing the names and descriptions of “blank” card objects on the fly. And all this other code I wrote depends on the cards being distinct objects.

If you don’t want >EXAMINE THREE OF CUPS to get the “You see nothing special about the Three of Cups” response, but you don’t want to add bespoke descriptions for all those cards, nobody would fault you for giving every card the same description, like

The description of a tarot card is usually "A thick card, printed with an arcane design."

The picking action

I really think you should handle the “picking” of cards with the built-in taking action. When you stick to built-in actions, a bunch of the work has been done for you. (On the other hand, when you add a new action that’s essentially synonymous with an existing action, you are probably creating problems.) The game text does tell you to “pick” a card, but if the player types in TAKE THREE OF PENTACLES the result should be the same, right? And all you have to do is add a synonym: Understand "pick [something]" as taking. (I know otistdog said that doesn’t work, but it works fine for me.)

Knowing which is the right card

The determine the correct card step runs down the Table of Correct Tarot Cards and picks the first row with a usedyet entry of “false.” And then it sets that value to “true” so that row won’t get picked again. You can edit the Table of Correct Tarot Cards to include all 36 of your correct answers, but each one needs a “false” entry under the “usedyet” column.

Digression Over

For the sake of completeness, I will point out that I have changed the Instead of taking a tarot card rule to refer to the new execute a tarot choice rule:

Instead of taking a tarot card:
	if the noun is the correct card:
		say "'That's correct!' says Madam Sosostris. ";
		execute a tarot choice;
	otherwise:
		say "'That's incorrect!' says Madam Sosostris. Am I spelling that right? Anyway, you have to start over.[paragraph break]";
		repeat through Table of Correct Tarot Cards:
			now usedyet entry is false;
		execute a tarot choice;

What remains is the new end the tarot challenge successfully step, which takes place when we try to pick a new card but there are none left in the Table of Correct Tarot Cards. I’m going to act like there’s more stuff to do after this challenge, and clean up the play area to prevent the player from messing with the cards and causing confusion:

To end the tarot challenge successfully:
	say "'That's the last one! Good job!'[paragraph break]Madam Sosostris packs up her cards and goes home.";
	remove Madam Sosostris from play;
	repeat with leftovercard running through tarot cards enclosed by the location:
		remove leftovercard from play.

Attached is the full source, with all the parts I didn’t change, and all the cards declared as unique entities so you don’t have to type that all out yourself. tarot challenge v2.txt (5.8 KB)

3 Likes