Let's play Zork + Colossal Cave Adventure

This will be a video let’s play with two players. One of us has played Zork but not Colossal Cave; the other has played Colossal Cave but not Zork. We’re going to take turns (alternating between “Z” episodes and “A” episodes) and guide each other through our respective games. After finishing both games, we’ll take a tour through their source code.

The versions we’ll be playing are revision 119 of Zork I and Donald Knuth’s literate programming port of 350-point Adventure (a.k.a. KNUT0350). If we had known better, we might have started with the more common revision 88 of Zork, but revision 119 leads to some funny moments, as you’ll see. The KNUT0350 version of Adventure is personally significant, for a reason that will be revealed.

We’ll spoiler-tag the written recap of each episode, for those who don’t want to know what’s going to happen in advance. But otherwise, you may consider this thread a place where people either know the games or are willing to have them revealed. Feel free to post comments and speculation without worrying too much about spoiler-tagging things.

Shout out to Chip and Ironicus, the best to ever do it.

10 Likes

Episode Z1

In this episode, we started by exploring the forest, finding a grating and a tall tree with a nest and a jeweled egg. (By some mischance, the egg got broken, revealing a clockwork canary inside.) We got into the house and discovered a trophy case and a hidden trap door. We found—to the player character’s peril—that “throw” has an assumed indirect object of “you” (in this revision 119 of Zork I, at least). Died three times to errant throws, and had to start over. Went up into the attic, and got eaten by a grue (as an experiment). Every time we die, our belongings get scattered over the overworld. Went to the canyon, found a rainbow but nothing to interact with, and came back. At last, descended the trap door…

Personal best: 35/350 points, rank of Amateur Adventurer.

Topics mentioned:

5 Likes

At about 0:02:57 in episode Z1 there is the question “am I a TAKE gamer or am I a GET gamer?” We didn’t know it at the time, but there is a poll on the forum for exactly that question:

1 Like

Yeah, those final unreleased versions do have some oddities, some of them probably caused by trying to update and unify the standard parser and verbs. The “throw” command is defined like this:

<SYNTAX THROW OBJECT (HELD CARRIED HAVE)
AT OBJECT (FIND ACTORBIT) (ON-GROUND IN-ROOM) = V-THROW>

So if you don’t specify what you want to throw an object at, it will look for anything with ACTORBIT. That’s apparently handled by the GWIM (“Get What I Mean”) routine. In the r88 source code, it never uses the ME object:

<COND (<GET-OBJECT ,P-MERGE <>>
<SETG P-GWIMBIT 0>
<COND (<==? <GET ,P-MERGE ,P-MATCHLEN> 1>
<COND (<EQUAL? <SET OBJ <GET ,P-MERGE 1>> ,ME>
<RFALSE>)>
<TELL "(">

In the r119 version, is has no such check:

       <COND (<EQUAL? <GET ,P-MERGE ,P-MATCHLEN> 1>
	      <SET OBJ <GET ,P-MERGE 1>>
	      <TELL "(">

I don’t remember off-hand if r119 has any game-breaking bugs, but you can probably expect a few surprises at least. (The one with the most noticeable changes is probably Zork III, where some of the text has been changed a bit.)

3 Likes

This was fun. I’m looking forward to the “A” episodes. I’m glad you’re using the Knuth port, as it’s more authentic to the original experience than many of the others.

But make sure you’ve got a recent-ish build to ensure you have all the bug fixes. The advent.w source that your links lead to appears to be up to date, but the nicely typeset code on Knuth’s site still has some of the bugs that have since been fixed. (And even the errata for the latest printing of the book doesn’t mention one of the fixes that was made to the sources.)

Anyway, Knuth’s is one of the more authentic ports. I say this begrudgingly. The other widely distributed ports made most of the same changes that Knuth did (dropping cave hours, using lowercase text, adding an input prompt), but they also tend to break or omit navigation features.

Then again, Knuth didn’t port the save feature (which actually wasn’t much of a feature of the program but of the operating environment), so good luck completing the game.

1 Like

Episode A1

We explored the forest in the overworld and entered the cave via the grate. Tempting fate by exploring without a light, we fell in a pit and died. Luckily, there is a reincarnation feature involving orange smoke; unluckily, it took us back outside the grate, which we had already re-locked…

On the next attempt, we discovered the magic word “XYZZY”, which at this point is understood as a form of extradimensional travel. We tested whether the fissure is jumpable (it’s not). We found a cheerful little bird, but for some reason couldn’t catch it in the cage. We got attacked a few times by dwarves, and managed to defeat them by throwing an axe. We encountered a huge green fierce snake in the Hall of the Mountain King and couldn’t find a way to get by it. Found a black rod whose purpose is unknown.

Personal best: 45/350 points, novice class adventurer.

Topics mentioned:

1 Like

Episode Z2

We started to explore the underground which we had just entered at the end of Z1. We found a chasm—it’s no more jumpable than the fissure in Adventure. We discovered some capacity limits, both in what the player can carry and in what containers (like the sack) can hold. Going south from the Cellar, we passed through the Gallery and the Studio, discovering (and destroying) a valuable painting on the way. The chimney in the studio is a way out of the underground, possibly the way we’re meant to take treasure out to put it in the case, but it allows you to take up only a few items at a time.

North of the cellar is the Troll Room. After exploring non-violent options, we eventually killed the troll with the sword. The experience of combat shows that the player character can get injured, and that injury reduces carrying capacity. After being killed once by the troll, we made the informal decision not to use the save/restore feature, and instead to play in a permadeath style, like Adventure.

Going east from the Troll Room took us to the Round Room. Choosing the SE exit at random, we toured through the Engravings Cave, Dome Room, Torch Room, Temple, and Egyptian Room, where there is a coffin and a sceptre. “XYZZY” is not a magic word in this game… but “hello sailor” might be! Leaving the temple, we found a mysterious mirror but were unable to do anything useful with it. We finished the episode at the Entrance to Hades!

New personal best: 57/350 points, rank of Novice Adventurer.

Topics mentioned:

If you’re curious why “take rock” moved the player south, read on.

  • The parser splits the input into words, W1 and W2.
  • The type of W1 determines what happens next. The relevant possibilities are motion, object, or action.
  • “TAKE” is an action word, so it sets the verb.
  • W1 is set to W2, and W2 is cleared, and it loops around.
  • Now W1 is “ROCK”, which you’d probably expect to be an object, but it’s actually a motion word.
  • A motion word, by itself, is a complete command, so the “TAKE” is ignored, and it attempts to execute the “ROCK” motion.
  • Executing the motion means looking for an entry that matches the current location (the 2-inch slit) and the motion word (“ROCK”). Sure enough, there is such an entry and it simply causes the player to move to the depression (where the grate is).

It’s very simplistic, but that simplicity let’s it handle a lot of common idioms at the cost of a sometimes surprising interpretation of some less common idioms.

But why is “ROCK” a motion rather than an object?

Adventure supports several types of navigation including, in many parts of the map, navigating by landmark. The description for the 2-inch slit location mentions that there’s bare rock downstream. By treating “ROCK” as a motion word, the player could quite naturally type “GO ROCK” or “GO DOWNSTREAM”. Since there’s no manipulatable rock object in the game, there’s no real point to treat it as anything other than a motion command.

Many players never realize that navigating by nearby landmarks is possible not only above ground but also in many places even in the cave. Some of the ports reinforce that by not implementing only the compass points (and up/down) for travel within the cave. Fortunately, the Knuth port is more faithful to the original in that regard.

4 Likes

In the CWEB version, this part of the parsing logic is in Sections 76–78. (As @aidtopia said, the PDF on literateprogramming.com is out of date with respect to the current version of advent.w, but for these sections it’s close enough. Beware of major spoilers if you start reading other sections—we’ll be going through this source code in detail in a future episode.)

http://literateprogramming.com/adventure.pdf#page=54

Our main task in the simulation loop is to parse your input. Depending on the kind of command you give, the following section of the program will exit in one of four ways:

  • goto try_move with mot set to a desired motion.
  • goto transitive with verb set to a desired action and obj set to the object of that motion.
  • goto intransitive with verb set to a desired action and obj = NOTHING; no object has been specified.
  • goto speakit with hash_table[k].meaning the index of a message for a vocabulary word of message_type.

Sometimes we have to ask you to complete an ambiguous command before we know both a verb and its object. In most cases the words can be in either order; for example, take rod is equivalent to rod take. A motion word overrides a previously given action or object.

So we parse one word, and based on that word set certain context variables (mot, verb, obj). Then we move word2 into word1 (the shift label in Section 76) and parse the second word by itself. Usually, the parsing of the second word combines with the already set mot/verb/obj to form a complete command. But when the second word forms a complete command by itself, the mot/verb/obj context is ignored. The program calls out a particular case of this: “A motion word overrides a previously given action or object.”

An example in HELP relies on this mechanism:

Some objects also imply verbs; in particular, “inventory” implies “take inventory”, which causes me to give you a list of what you’re carrying.

TAKE is a transitive action word (needs an object) and INVENTORY is an intransitive action word (doesn’t have an object). The program parses TAKE and sets verb = TAKE, but then the second word INVENTORY is treated as a complete command in itself, ignoring the already set verb. So the situation is actually the opposite of what HELP says: it’s not that TAKE is automatically supplied when only INVENTORY is given, but rather that the TAKE in TAKE INVENTORY is ignored.

The same thing happens with action words other than TAKE:

* inventory
You're not carrying anything.
* take inventory
You're not carrying anything.
* read inventory
You're not carrying anything.
* throw inventory
You're not carrying anything.
* eat inventory
You're not carrying anything.

But not JUMP INVENTORY, because JUMP is a motion word like SOUTH, not an action word. And while TAKE ROD and ROD TAKE are equivalent, the same is not true for INVENTORY TAKE. In this case INVENTORY is ignored, as if you had typed only TAKE.

* jump inventory
I don't know how to apply that word here.

You're at end of road again.
* south inventory

You are in a valley in the forest beside a stream tumbling along a
rocky bed.
* inventory take
Take what?

That’s right. I did not make much use of the named-location motion words when I first played through the game, even though HELP does tell you about them: “To speed the game you can sometimes move long distances with a single word. For example, ‘building’ usually gets you to the building from anywhere above ground except when lost in the forest.” Part of the problem is that these words don’t always work the way it seems they should. For example, from cobbles or debris you can type PIT to go directly to the spit room (brink of small pit), but from spit only DEBRIS works, not COBBLES, even though COBBLES works from other rooms (namely debris and inside). And in one case the connection seems bugged: from emist (east end of Hall of Mists), Y2 takes you to not to y2, but to the adjacent room jumble.

2 Likes

Episode A2

We tried out two important magic words: INFO and HELP. HELP gave a helpful hint about the black rod having a side effect on the bird. Having caught the little bird, we took it to the Hall of the Mountain King, with the shameful intention of feeding it to the snake. Instead, the little bird conquered the snake in combat. Beyond the Hall of the Mountain King, we found a room with a rock marked “Y2”. (Y2 doesn’t seem to be a magic word like XYZZY, though.) Found a window overlooking a pit, opposite which there was a mysterious shadowy figure. Nothing we could think of worked to cross the pit and encounter the figure. Trying to jump earned us another broken neck. Finding a way around to the opposite window was our motivator for the rest of the episode.

Exploring onward, we found a room with a giant clam in it, too large to carry out. We proceeded next to Bedquilt, then an anteroom where there is an issue of Spelunker Today magazine. Then we were killed by a dwarf—so they can get you with their sharp nasty knives.

From the anteroom, we stumbled into Witt’s End, a room from which escape is difficult. Continuing west from Bedquilt, we passed through the Swiss Cheese Room and the Soft Room, where there is a velvet pillow. Then we were unexpectedly attacked by a pirate, who stole all our treasure (some silver bars) and hid it in a maze somewhere. We entered the Twopit Room—could one of these be the pit under the window? One of the pits has oil in it. By first pouring out the water, we can fill the bottle with oil. In the other pit, there is a tiny little plant, which demands (what else?) water.

Topics mentioned:

1 Like

The audience for the complex junction joke was small, but appreciative, I can assure you!

2 Likes

“There’s something that just looks so passive-aggressive about OK in all caps … with a period at the end of it.”

I guess I’m old because I was utterly bemused by that reaction.

I just now happened to stumble upon a comment1 pointing out that Don Wood’s version2 did not have the period. Knuth added it.3

Knuth is even older than I am, so I guess we’re lucky he didn’t change it to “O.K.” Or even “Oll korrect!”4 ;-)

Interestingly (to me), changes to this one response could provide evidence of a port’s lineage.

  • The oldest SUPN0350 source I’ve found changed the case to “Ok” but left off the period. I don’t know whether that was done by Dave Supnik or if he inherited that alteration from Kent Blackett BLKT03505.

  • By SUPN0350r4, it had become “Okay” without a period.


1 The comment is on line 148 of this source file, which is an update of Donald Knuth’s code to a slightly more modern dialect of C.

2 I confirmed that WOOD0350 source code does not print “OK” directly. It uses “arbitrary message” 54 from section 6 of the data file, which is indeed “OK” (sans period). (I checked both v1 and v2.) This seems to be the case all the way back to CROW0000.

3 Knuth §14: default msg [RELAX] = "OK.";

4 The Hilarious History of ‘OK’

5 Unfortunately, I haven’t found a working link to BLKT0350.

3 Likes

Episode Z3

We started where we left off in Z2, at the gates of Hades. Not yet knowing a way in, we found our way back to the Round Room. On the way, we broke the large mirror in the mirror room, which did not seem to do anything useful. With high hopes, we waved the sceptre at the chasm—and nothing happened. In frustration we threw the sceptre, which had the familiar effect of killing the player character.

But something was different this time. Instead of resurrecting in the forest, we were back at the gates of Hades, and everything now seemed “indistinct, bleached of color, even unreal.” We could not touch items or interact with much. Somehow we could see things despite not carrying a lamp. In this strange state we continued the exploration.

Intending to go west from the Round Room, we went east and arrived at the Loud Room. There is a puzzle here, as our commands merely echo back at us. Again intending to retreat to the west, we went east through a damp cave to White Cliffs beach: an apparent dead end, and not the same shore we had found in the overworld in Z1.

We discovered that WAVE OBJECT is an oracle that reveals the existence or nonexistence of objects in the game. If the object is known to the game, the response will be “You don’t have that!”, but if it’s not, the game will instead say “I don’t know the word ‘OBJECT’.” By this trick we learned there must be a diamond somewhere in the game (and a set of teeth?!?), but we didn’t push it too far.

We tried the verb ECHO in the Loud Room, which had the effect of making the room quiet. But we still could not pick up the platinum bar that was in the room. Maybe because we’re a ghost now?

Going up from the Loud Room we found Flood Control Dam #3 and its surrounding rooms, which were full of tools and controls that we could not interact with. At the base of the dam there was a pile of plastic, perhaps an inflatable life raft. There’s a reservoir we could not cross, and a stream that doesn’t lead anywhere. Pottering around, we found another way back to the Round Room. We considered entering the forbidding hole west of the troll room, but at the last minute decided to try one last thing. On entering a PRAY command at the altar in the temple, trumpets sounded, and we found ourselves returned to corporeal form, once again in the forest.

Topics mentioned:

Originally, there was a way to save your state in Adventure, but it was tightly coupled to features of the operating system and the machine. Most of the ports dropped that functionality along with the “wizard” mode that allowed system administrators to configure the game for their users.

On the PDP-10, you could take a snapshot of your process’s memory. These snapshots were called “core images.” Load a previously-saved core image into a process, and you could resume execution right where you left off.

Here’s what would’ve happened if you had typed SAVE in the original game:

YOU'RE AT END OF ROAD AGAIN.

SAVE

I CAN SUSPEND YOUR ADVENTURE FOR YOU SO THAT YOU CAN RESUME LATER, BUT
YOU WILL HAVE TO WAIT AT LEAST 90 MINUTES BEFORE CONTINUING.

IS THIS ACCEPTABLE?

YES

OK

BE SURE TO SAVE YOUR CORE-IMAGE...

And then you’d have to type whatever the incantation was to save your core image.

A short while later, you might try to load your core image back into your process and see something like this:

THIS ADVENTURE WAS SUSPENDED A MERE 10 MINUTES AGO.

EVEN WIZARDS HAVE TO WAIT LONGER THAN THAT!

Yeah, that’s right. It would lock you out so that you couldn’t rapidly iterate in a save-die-restore loop. The default lockout time was 90 minutes, but that could be configured by the system administrator who installed the game on your system. If you could prove you were a wizard, you could resume in one-third of the lockout time.

When you tried again after waiting the requisite amount of time, you’d load your core image and the game would pick up right where you left off.

In the mean time, you could try to peek inside your core file. It contained not only the game state, but all of the text in the game: descriptions, responses, and vocabulary. To thwart players browsing for clues, the vocabulary table was lightly obfuscated (a bitwise XOR of the character values with the corresponding values in ‘PHROG’).

3 Likes

I think you’re right, it looks like an anti–save scumming measure. The way NetHack does it is it keeps the save files in a special area where ordinary users cannot access them. You can’t load a game from an arbitrary file, but only from the file the game previously saved itself. A saved game file is deleted once it is loaded, so it cannot be loaded more than once. (Naturally it’s possible to work around these measures, they are really only there to establish an intended style of play.) With Adventure, I suppose that it is because the user that saves the core file, and not the game, that a similar technique would not work, and so the 90-minute delay was added, as a discouragement against repeated save and restore. It would be enough to prevent a strategy of saving after every turn, at least.

After a core file is sufficiently aged, from what you’ve described, it seems like you could restore it as many times and as rapidly as you want. Like if there were a point where you wanted to try five different mutually exclusive actions, you could save the game, wait 90 minutes, then try all five actions.

My understanding is that later games more embraced the save/load mechanic, and that aspects of their design, like unpredictable instant deaths, should be seen in that light.

Wow! PHROG would make a great magic word in a new adventure game. I had seen some reference to string obfuscation in Adventure but never knew how it worked. Here it is in the source code:

Initial filling of the hash table: advent.for#L325

C  HERE WE READ IN THE VOCABULARY.  KTAB(N) IS THE WORD NUMBER, ATAB(N) IS
C  THE CORRESPONDING WORD.  THE -1 AT THE END OF SECTION 4 IS LEFT IN KTAB
C  AS AN END-MARKER.  THE WORDS ARE GIVEN A MINIMAL HASH TO MAKE READING THE
C  CORE-IMAGE HARDER.  NOTE THAT '/7-08' HAD BETTER NOT BE IN THE LIST, SINCE
C  IT COULD HASH TO -1.

1040	DO 1042 TABNDX=1,TABSIZ
1043	READ(1,1041)KTAB(TABNDX),ATAB(TABNDX)
1041	FORMAT(G,A5)
	IF(KTAB(TABNDX).EQ.0)GOTO 1043
C  ABOVE KLUGE IS TO AVOID AFOREMENTIONED F40 BUG
	IF(KTAB(TABNDX).EQ.-1)GOTO 1002
1042	ATAB(TABNDX)=ATAB(TABNDX).XOR.'PHROG'
	CALL BUG(4)

Lookup at runtime: advent.for#L2322

C  LOOK UP ID IN THE VOCABULARY (ATAB) AND RETURN ITS "DEFINITION" (KTAB), OR
C  -1 IF NOT FOUND.  IF INIT IS POSITIVE, THIS IS AN INITIALISATION CALL SETTING
C  UP A KEYWORD VARIABLE, AND NOT FINDING IT CONSTITUTES A BUG.  IT ALSO MEANS
C  THAT ONLY KTAB VALUES WHICH TAKEN OVER 1000 EQUAL INIT MAY BE CONSIDERED.
C  (THUS "STEPS", WHICH IS A MOTION VERB AS WELL AS AN OBJECT, MAY BE LOCATED
C  AS AN OBJECT.)  AND IT ALSO MEANS THE KTAB VALUE IS TAKEN MOD 1000.

	IMPLICIT INTEGER(A-Z)
	COMMON /VOCCOM/ KTAB,ATAB,TABSIZ
	DIMENSION KTAB(300),ATAB(300)

	HASH=ID.XOR.'PHROG'
3 Likes

Episode A3

We returned to the Twopit Room with water in the bottle, in order to water the plant we met last time. A little water caused the plant to grow into a beanstalk and demand even more. We trekked all the way back out of the cave (meanwhile depositing a treasure in the building for the first time) to refill the bottle at the stream. Watering the plant a second time caused it to grow even taller, up to the hole above the pit. But our suspicion was not confirmed: this is apparently not the same window on pit where we saw the shadowy figure.

The new path led us to a new place, the Giant Room, where there is a nest of golden eggs and a mysterious inscription: FEE FIE FOE FOO. The way north was blocked by a massive, rusty, iron door that could not be opened—our idea was that we needed the giant to come and open it for us. Taking the golden eggs did not summon the giant, as we had feared. The FEE FIE FOE FOO magic word seems like it teleports the golden eggs out of our inventory and back to the Giant Room—what use is that?

On passing through the Y2 room, we experienced something new: a hollow voice saying “PLUGH”. This is a magic word that warps us between Y2 and the building outside. In a side chamber of the Hall of the Mountain King we found some rare coins, which were immediately stolen by the pirate.

From the west end of a long hall, we stumbled into a maze of twisty little passages, all different. This not being our first IF rodeo, we started dropping items to mark rooms we’d been to. Random exploration found us in a dead end with a vending machine that promises fresh batteries in exchange for coins—if only we hadn’t lost the coins to the pirate. There are a lot of rooms in the maze, more than we had items for. But wait a minute—these rooms are not as identical as they seemed at first! The room descriptions vary: “maze of twisting little passages”, “maze of little twisting passages”, “twisty little maze of passages”, etc. We continued mapping things out, but finished the episode still lost in the maze.

New personal best: 73/350 points, novice class adventurer.

Topics mentioned:

3 Likes

Episode Z4

Buckle up, maze fans, it’s time for a maze episode!

At the end of Z3 we had just woken up, empty-handed, in the forest, after being resurrected from a state of living death. We explored some more of the overworld and recovered some of our belongings. We found the lantern in the living room.

With the intention of finally returning at least one treasure to the trophy case, we returned to the Loud Room, where we had previously seen a platinum bar that we were unable to pick up while in ghost form. But the bar was not in the room where we had left it… :thinking: Well, scratch that idea. Might as well finally check out that forbidding hole west of the Troll Room… and what could it be but a maze of twisty little passages, all alike.

We spent the rest of the episode mapping out the maze in a spreadsheet, with rooms as rows and directions as columns. Unlike the maze we had just seen in Adventure, this maze truly was “all alike”, necessitating the strategy of dropping items to distinguish the rooms. We encountered a thief, in three different rooms, as well as the “lean and hungry” gentleman, who may be the same person. The maze was seeming like it might be nice and compact until we went “up” to a room with a skeleton, a bag of coins, a key, and a passage into a deeper part of the maze. Many rooms and much inventory management later, we found a Grating Room with a skull-and-crossbones lock. Though we could not unlock it, because we had dropped the key as a marker item, presumably this is the grating under the leaves in the forest. Not counting dead ends, we mapped 15 rooms, fully or partially, before the lamp ran out and we were eaten by a grue.

N E S W NE SE SW NW UP DOWN
Troll A
A A Troll B D / / / / / /
B / C A / / / / / / D
C D / / B / / / / S /
D A X1 / C / / / / / /
X1 / / D / / / / / / /
S C X2 / / / / E / / /
X2 / / / S / / / / / /
E / F / E / / / / I S
F / G H E / / / / H X1
G / / / G F X4
H / / F
I E J K L / / / I / M
J / I / K / / / / M /
K / I J M / / / / / L
L X3 K / / / / M / I S
X3 / / L / / / / / / /
M / / / / Grating / L K / J
Grating / / / / / / M / clearing? /
X4 G

Topics mentioned:

Episode A4

We returned to finish mapping the maze of twisty little passages, all different. (Taking advantage of our new magic word PLUGH to warp straight to Y2 from the building.) We quickly found our way back to the dead end with the vending machine, this time having the coins in hand to exchange for fresh batteries for the lantern.

There are 12 rooms in all, including the room with the vending machine. Most of the rooms are connected to 10 others via all the possible directions (N, E, S, W, NE, SE, SW, NW, UP, DOWN). As fate would have it, we found the exit of the maze only after exploring almost every direction from every room. It is DOWN from the “maze of twisty little passages” (the bottle room).

We recovered our belongings from the maze and resume our expedition. We found, at last, the west end of the Hall of Mists. Going through a hole to the south we stumbled into… a maze of twisty little passages, all alike!

Topics mentioned:

“Let’s go back into the safer part of the cave… Oh, wait, what happened? Oh, no. I didn’t mean to do that. I mixed up east and west like I always do.”

“This is not what I intended to do. Oh, no. Did I go east when I meant to go west again?”

This (from Z3) was not a bit—I really did confuse east and west twice in a row and end up two rooms away in the wrong direction. I guess I’m not the only one who has this difficulty. I just now found the below thread which was validating:

3 Likes

It’s so weird. I’ve never confused north and south. I wonder if it’s somehow physiological - the body is (generally) mirrored left to right but not up and down, and maybe that’s part of it fundamentally?

2 Likes