Heartstone Update 1.4: The Immersion Update
Nov 26, 2025
Update 1.4 Announcement
Hello, fellow devout followers of Mreska!
This is going to be a long one…
To celebrate the launch of InTheAttic.dev, I wanted to showcase the newest build of The Heartstone Caverns, what I am calling The Immersion Update.
The goal is to make the player feel more at home within the world of Valeria, by including responsive audio and a growing map of locations you visit. While imagination is staying the main graphics renderer, audio and spatial awareness is a core part of immersion.
The biggest systems to showcase are the map system and the audio manager, but there are some other smaller changes and fixes that make the flow of the map consistent.
There is a lot that I want to showcase in this post, as a lot of the work this update is not seen directly in the game. Let’s get into it, by first looking at:
The Audio Manager!
For a long time, the engine has been purely text-based. Today, I announce the implementation of a fully data-driven, cross-language Audio Engine.
As readers know, because our game runs on a unique stack, Python (via Pyodide) for game logic and JavaScript for the frontend, playing a simple sound wasn't so simple. Python doesn't have access to your browser's speakers, and JavaScript doesn't know when a monster has been hit.
I built a communication bridge to solve this:
- The Brain (Python): The game logic determines what should happen. When you enter a crypt, the Python engine queues a bgm (background music) event. When you swing a sword, it queues an sfx event.
- The Courier (JSON): At the end of every turn, Python serializes these events into a JSON string. This was a crucial fix to avoid object conversion issues between the languages.
- The Mouth (JavaScript): The frontend parses this queue and uses the Web Audio API to fetch and play the assets asynchronously.
While I still need to work on gathering sounds and filling them into the game, a lot of the core sound features one would expect are present.
Spells can have their own unique effects, swords and weapons can have unique hit and pick up effects, books/items can have voice over narration, combat as a whole has sfx for attack and on hit, rooms can all have their own ambient room tones, and of course all of the music.
The Options menu now includes a full suite of sliders for Master, Music, SFX volume, saving your preferences between sessions via LocalStorage.
The music is a state itself, it recognizes when you enter certain areas or encounter specific enemies. It can flow, shift, and play tracks based on what the user does in game. Further updates will add more sound and make the world feel even more lived in. One of the things I need to do is record nature soundscapes as I have fun doing that.
I wanted to add in a base amount of sounds in the 1.4 update to see how it felt to play first. I also still need to work on normalizing all of the sfx and music to be fully consistent.
The Map System
One of the biggest challenges in text adventures is spatial grounding. It’s easy to get lost in a dungeon when the world exists entirely in text. You enter a room, go north, then west, then west again, then northeast, and suddenly you aren't quite sure where the entrance was relative to where you are now.
This feature has been one of my dream additions for a while. To make the world feel more connected and to give players a sense of destination, I introduced a fully interactive, dynamic Visual World Map.
The Visual Style
I wanted a look that was akin to my backend map on Twine, but fitting the fantasy aesthetic of the game. The map uses a node-link system:
- Rooms are represented by rectangular nodes.
- Paths are drawn as connecting lines.
- The Player is highlighted to show the current position.
- Fog of War: The map is reactive. You only see rooms you have visited and the paths connecting them. The world unfolds as you explore.
How It’s Made: The Map System
Initially, I tried to generate the map relative to the player. If you moved north, the next room was drawn at (0, -1). However, this caused a drift of sorts, where if you walked in a circle, the map would slowly warp, and rooms wouldn't line up correctly.
I switched to a Fixed Anchor System. The engine now designates a "Start Room" as the permanent (0,0) coordinate for the world. Every time you open the map, the Python backend runs a Breadth-First Search (BFS) algorithm across the entire database of rooms to calculate their absolute grid positions before sending the data to the JavaScript renderer.
Text adventures often have non-Euclidean geometry (going west might take you to a room that is 3 miles away in the world). To handle this, the map system supports Distance Modifiers.
I can tell the engine, "The path West from Dirt Road (West) is 2.2x longer than normal." The map renderer stretches that specific connection, allowing us to visualize long roads or distant towers without them overlapping the shops next door. (I was going crazy trying to get the blacksmith shop in Oakhaven not to collide with the rat cave, for instance.)
Procedural generation is great, but sometimes you just want a room right there. I implemented a coordinate override system. While the engine can auto-guess where rooms belong, I can manually "Pin" a room to specific decimal coordinates (e.g., [1.5, -4.2]) in the data files. The engine respects these pins as absolute truth and builds the rest of the procedural map around them. The auto system would be great for a game that is just a few rooms, or has teleporting rooms where it is in smaller separate chunks.
The Hidden Gem Feature
This is the feature in the update I am most proud of. To make sure the map looks perfect for my sprawling RPG, I didn't want to guess coordinates in a text file, reload the game, check the map, and repeat.
So, I built a Map Editor directly into the game engine. (Yeah, a lot of the fun stuff in this update is stuff the player doesn’t directly see. But it’s setting the stage for this engine to be used in other projects, and by other people eventually.)
- Dev Mode: When enabled in the backend, a "Edit Layout" button appears on the map.
- Drag & Drop: I can click and drag any room node to a new position in real-time. The JavaScript frontend instantly calculates the new grid coordinates and syncs them to the Python backend.
- Source Tracking: When I click "Save," the Python engine looks at every room I moved, remembers which specific .json file that room belongs to (e.g., forest.json vs caves.json), reconstructs the file with the new coordinates, and triggers a browser download for the updated data files.
This turns the game itself into the level editor, saving hours of development time. I have plans for eventually cloning this system for an item editor, maybe even a room editor. It’s really all just about breaking down the tags that are in each .json database entry and knowing which one to add or overwrite.
UI Changes
To accommodate the new map the UI has received a refinement:
- Collapsible Sidebar: The Inventory, Stats, and Location tabs can now be collapsed to give the map more screen real estate. You can now hold a lot of items and simply collapse the inventory to see what spells you have.
- Controls: The map supports panning (Arrow Keys/WASD/Mouse Drag) and zooming (Scroll Wheel).
- Focus: The map automatically centers on the room the player is currently standing in. IT SHOULD– there may be some bugs. The next update will address it.
Alright, enough talking! Since I am releasing this earlier than I expected, I can say with some certainty that this will not be the last update of the year. I will use the space on this site to carve out a plan of what is to come in the next update.
Overall, the immersion update completely changes the feel of exploration in The Heartstone Caverns, making the world feel larger and more connected.
I can't wait for you to try it out!
Peace and love to all, (except Big Orange and his sad turkey pardon standup routine)
Connor | YodaInTheAttic