Nyxatar Heroes Saga - Advanced Usage Guide
Welcome, aspiring demigod or meticulous chronicler! This guide provides detailed information for users looking to customize their Nyxatar Heroes Saga experience beyond the basic setup. Here you'll find details on running multiple instances, operating the game as a persistent background process, diving deep into script customization, and understanding some of the development and testing insights.
Basic Command-Line Customizations
Beyond the fundamental run commands found on the main project page, you can control the terminal's scrolling log display at launch using these arguments:
--log-lines NUMLINES
: Sets the maximum number of scrollable log lines displayed on screen. For example,--log-lines 50
will display 50 lines. The script's default is 25 (controlled byMAX_LOG_LINES
in the script).--log-width WIDTH
: Sets the maximum character width for each log line before truncation. For instance,--log-width 100
sets it to 100 characters. Setting this to0
disables truncation, allowing lines to be as long as needed. The script's default is 84 (controlled byLOG_LINE_MAX_WIDTH
).
These options can be combined with each other and with the --enable-game-saving
flag.
Example Usage:
To run the game with saving enabled to the default file, displaying 30 log lines with a maximum width of 100 characters:
python3 nyxatar_heroes_saga.py --enable-game-saving --log-lines 30 --log-width 100
To run in RAM-only mode with 40 log lines and unlimited width (no truncation):
python3 nyxatar_heroes_saga.py --log-lines 40 --log-width 0
Managing Multiple Saved Sagas
While you can run many instances of Nyxatar Heroes Saga in RAM-only mode without issue, managing multiple sagas that save their progress requires careful attention to avoid data corruption.
The Importance of Unique Save Files
If you use the --enable-game-saving
command-line flag without specifying a custom path, the game defaults to saving in nyxatar_heroes_saga_save.json
(this filename is set by the DEFAULT_SAVE_FILENAME
constant in the script) within the same directory as the script.
Crucially, running multiple instances simultaneously that all attempt to save to the same file path will lead to data from one instance overwriting another. This can corrupt your saga or cause you to lose progress.
Using Custom Save File Paths
To run multiple sagas concurrently with saving enabled for each, you must provide a unique custom save file path for each instance. This is done by providing a full or relative path to the --enable-game-saving
flag.
Syntax:
python3 nyxatar_heroes_saga.py --enable-game-saving /path/to/your/custom_save_name.json
Example for Linux/macOS using absolute paths:
python3 nyxatar_heroes_saga.py --enable-game-saving /home/user/my_sagas/saga_alpha.json
python3 nyxatar_heroes_saga.py --enable-game-saving /home/user/my_sagas/saga_beta.json
Example for Windows using absolute paths:
python3 nyxatar_heroes_saga.py --enable-game-saving C:\Users\YourUser\Documents\MySagas\nhs_instance1_save.json
python3 nyxatar_heroes_saga.py --enable-game-saving C:\Users\YourUser\Documents\MySagas\nhs_instance2_save.json
By specifying a unique JSON file for each instance, you ensure their progress is saved independently and safely.
Understanding and Managing Save Files
When game saving is enabled, Nyxatar Heroes Saga employs several mechanisms to protect your progress and provide information. Save files are stored in JSON format, making them human-readable if you wish to inspect them (though manual editing is highly discouraged and can easily corrupt your saga).
Periodic Saves
To prevent data loss from unexpected interruptions, the game automatically performs a periodic save.
- This is governed by the
TICKS_BETWEEN_PERIODIC_SAVES
constant in the script (default is 3600). IfGAME_TICK_DELAY
is 1.0 (one second), this means a periodic save occurs roughly every hour of real time. - A log message "Periodic save complete." will appear when this happens.
Backup Files (`.bak`)
Each time the game successfully saves (either periodically or upon graceful exit), it first creates a backup of your existing save file.
- If your save file is
my_saga.json
, the backup will bemy_saga.json.bak
. - If the game tries to load a save file and cannot find it, it will automatically attempt to load from the corresponding
.bak
file. This can help recover from a situation where the main save file was accidentally deleted or became corrupted during the last save attempt (e.g., due to a power outage).
Crash Files (`.CRASH`)
In the unfortunate event of a critical error or unhandled exception within the game, it will attempt to save its current state to a special .CRASH
file.
- If your save file is
my_saga.json
, the crash file will bemy_saga.json.CRASH
. - This file will contain the game state much like a normal save, but will also include information about the error and a traceback, which can be invaluable for debugging if you are a developer or reporting a bug.
- Important: If you encounter a
.CRASH
file, it's advisable to make a copy of it and its corresponding.bak
file before attempting to resume. You might be able to resume by renaming the.bak
file to your main save file name. The.CRASH
file itself is not automatically loaded but serves as a diagnostic tool and a last-resort data recovery point.
Save File Version (`GAME_STATE_VERSION`)
The script includes a GAME_STATE_VERSION
constant (e.g., "0.1.0"). This version string is embedded in your save file.
- If you load a save file created with a different
GAME_STATE_VERSION
than the one in your current script, the game will attempt to load it but will print a warning. - Significant changes to the save structure between game versions might lead to loading issues or unexpected behavior. This versioning helps track compatibility.
Running Unattended in the Background (Linux/macOS/etc.)
If you want Nyxatar Heroes Saga to continue running and progressing uninterrupted (e.g., on a server or a machine where you might close the terminal), tools for background operation are recommended. On Linux, macOS, or other **NIX-like systems, utilities such as nohup
(often used with &
) or terminal multiplexers (e.g., tmux
, screen
) are ideal.
Example using `nohup`
nohup
(no hang up) allows a command to keep running even after the user logs out.
nohup python3 nyxatar_heroes_saga.py --enable-game-saving ~/my_nyxatar_saga_instance_1.json > ~/my_nyxatar_saga_instance_1.log &
This command:
- Runs the saga with saving enabled (essential for unattended runs).
- Specifies
~/my_nyxatar_saga_instance_1.json
as the unique save file path for this instance. - Redirects all terminal output (standard output and standard error) to
~/my_nyxatar_saga_instance_1.log
. This log file will capture all game messages. - The
&
at the end places the process in the background, freeing up your terminal.
Remember to use a unique save file path for each concurrently running saved instance. Please consult the documentation for nohup
, tmux
, or screen
for their specific usage details and how to manage backgrounded processes.
Using `systemd` for Long-Term Grinding on Linux
For a robust, persistent grinding experience on modern Linux systems (like Ubuntu, Fedora, Debian), systemd
can manage the saga as a background service. This properly handles starting automatically on login (for user services), automatic restarts on failure, and integrates with system logging via journalctl
, making it more robust than manually using nohup
.
The easiest way for personal use is often a User Service (doesn't require root privileges):
- Create the directory
~/.config/systemd/user/
if it doesn't already exist:
mkdir -p ~/.config/systemd/user/
- Create a systemd service definition file. For example, name it
~/.config/systemd/user/nyxatar_heroes_saga_instance_alpha.service
. Paste the following content into it, adjusting paths as needed:
[Unit]
Description=Nyxatar Heroes Saga - Persistent Grind Instance Alpha
After=network.target
[Service]
Type=simple
# ADJUST THESE PATHS! Use full absolute paths.
# Systemd user services automatically expand ${HOME} to your home directory.
# Example: ExecStart=/usr/bin/python3 ${HOME}/games/nyxatar/nyxatar_heroes_saga.py --enable-game-saving ${HOME}/games/nyxatar_saves/alpha_save.json
ExecStart=/usr/bin/python3 /full/path/to/nyxatar_heroes_saga.py --enable-game-saving /full/path/to/your_unique_alpha_save.json
# Automatically restart if it exits unexpectedly (e.g., script crashes)
Restart=on-failure
# Wait 5 seconds before attempting a restart
RestartSec=5s
# Optional: Set a working directory if your script relies on relative paths for assets (though NHS usually doesn't)
# WorkingDirectory=/full/path/to/script_directory
[Install]
# Start this service when your user's session starts
WantedBy=default.target
Key point: You MUST replace the example paths in ExecStart=
with the correct, full absolute paths to your Python 3 executable, the nyxatar_heroes_saga.py
script, and your desired unique save file location for this specific instance. Using --enable-game-saving
is crucial for persistence!
- Tell systemd to reload its user configuration files:
systemctl --user daemon-reload
- Enable the service (to start automatically every time you log in) and start it immediately:
systemctl --user enable --now nyxatar_heroes_saga_instance_alpha.service
- Check if it's running correctly: (Press 'q' to exit the status view)
systemctl --user status nyxatar_heroes_saga_instance_alpha.service
Look for "active (running)". If it failed, journalctl
(see next step) will have error details.
- View its live log output: (Press Ctrl+C to stop viewing logs)
journalctl --user -u nyxatar_heroes_saga_instance_alpha.service -f
To view just the last 30 lines (without paging):
journalctl --no-pager --user -u nyxatar_heroes_saga_instance_alpha.service -n 30
That's it! Your Nyxatar Heroes Saga instance will now be managed by systemd
, running reliably in the background whenever your user session is active. To run multiple independent sagas, create multiple .service
files (e.g., nhs_beta.service
) ensuring each has a unique Description
and ExecStart
line pointing to a unique save file.
Important Note on Uniqueness with systemd
: While systemd
ensures this specific service unit (e.g., nhs_alpha.service
) doesn't run multiple instances of itself, it doesn't automatically prevent other processes (like manual runs from the terminal, or a differently named service file) from potentially accessing the same save file path defined in ExecStart=
. To avoid save file corruption, it remains crucial to ensure that any persistent instance of the saga, however launched, uses its own completely unique save file path provided via the --enable-game-saving
flag.
In-Depth Script Customization
For those who wish to delve into the very fabric of Nyxatar's reality, the Python script (nyxatar_heroes_saga.py
) offers a gateway. Numerous global constants, defined near the beginning of the file, control core aspects of the game. Modifying these allows you to fine-tune game balance, probabilities, content generation, and overall feel. (For more on game balance and features, see About the Saga).
A Word of Caution: Editing these constants can significantly alter the intended game experience, difficulty, and stability. It's highly recommended to:
- Back up the original
nyxatar_heroes_saga.py
script before making changes. - Make incremental changes and test them.
- Keep notes on what you've changed and why.
- Be aware that future game updates might conflict with your modifications if they alter the same constants or underlying logic.
Below are key categories and notable constants you might consider tweaking. Refer to the script's comments for more details on specific variables.
Game Loop & Core Engine
These constants affect the fundamental rhythm and speed of the game.
GAME_TICK_DELAY
: Seconds per game tick (default:1.0
). Lower values speed up the game;0
runs at maximum processing speed (as used in Smoke Tests).PROGRESSION_RATE
: A universal multiplier for both XP and Gold gain (default:1.0
). Higher values accelerate character progression.MAX_LOG_LINES
/LOG_LINE_MAX_WIDTH
: Default settings for the on-screen action log. These can also be overridden by command-line arguments.
Saving and Loading
Controls how and when the game state is persisted.
DEFAULT_SAVE_FILENAME
: The default name used for the save file if no path is specified with--enable-game-saving
.TICKS_BETWEEN_PERIODIC_SAVES
: Defines how many game ticks pass before an automatic periodic save occurs (default:3600
). With a 1-second tick delay, this is one hour.GAME_STATE_VERSION
: An internal version string for the save file structure. Altering this is not recommended unless you are adapting an old save to a new script version with structural changes (a very advanced maneuver).
XP, Leveling, and Tiers
These constants shape the hero's journey from a fledgling adventurer to a seasoned veteran.
BASE_XP_START
,XP_PER_LEVEL_FACTOR
,XP_POWER_SCALING
: These collectively determine the XP required to reach the next level.XP_POWER_SCALING
has a large impact on how steep the leveling curve becomes at higher levels.BASE_XP_GAIN_POWER_SCALING
,ACTION_XP_BASE_UNIT
: Influence how much XP is gained from various actions, scaling with the hero's level.LEVELS_PER_WORLD_TIER
: The number of hero levels required to advance to the next World Tier, which in turn affects monster difficulty and loot quality. (See World Tiers feature description).
Economy & Inheritance
Governs wealth accumulation and what is passed to the next generation.
BASE_GOLD_POWER_SCALING
: How gold rewards from actions scale with the hero's level.GOLD_INHERITANCE_ROBBERY_CHANCE
: The probability (0.0 to 1.0) that an heir loses all inherited gold due to "grasping relatives."LEGACY_GOLD_LOG_THRESHOLD
: The minimum amount of inherited gold that needs to be passed on for a specific log message about the amount; otherwise, a generic "empty pockets" message is shown.
Combat & Stats
Defines hero survivability and combat prowess.
BASE_HP_AT_LVL_1
,FLAT_HP_PER_LEVEL
,CON_HP_MULTIPLIER
,HP_GAIN_PER_LEVEL_FLAT
,HP_GAIN_PER_LEVEL_CON_DIVISOR
: Various components that determine a hero's Hit Points.D20_CRITICAL_HIT
: The die roll result (on a D20) that constitutes a critical hit in combat.
Death & Survival
The chances of a hero meeting their True Death.
DEATH_CHANCE_ON_OVERWHELMED_BASE
: Base probability of True Death when HP reaches 0 from a normal encounter.DEATH_CHANCE_OVERWHELM_OVERKILL_BONUS
: Additional chance if the damage taken was significantly high.DEATH_CHANCE_OVERWHELM_TIER_REDUCTION_FACTOR
: Reduces death chance based on World Tier.NEMESIS_DEATH_CHANCE_IF_HERO_LOSES
: Higher chance of True Death if defeated by a Nemesis monster.- Constants like
DEATH_CHANCE_RISKY_ACTION_BASE
,DEATH_CHANCE_REST_AMBUSH_BASE
,DEATH_CHANCE_MEDITATE_ACCIDENT_BASE
: Govern chances of death from specific non-combat activities.
Item & Monster Generation
Controls the variety and power of foes and treasures.
MONSTER_TIER_PREFIXES
: A list of lists, providing adjectives for monsters based on their World Tier.MAX_ITEM_PLUS_IDX_PER_TIER
: A dictionary mapping World Tiers to the maximum index inITEM_QUALITIES
that can drop, effectively capping item quality per tier.ITEM_QUALITY_ROLL_COMMON_MAX
,ITEM_QUALITY_ROLL_UNCOMMON_MAX
: Probabilities determining if an item is common, uncommon, or rare+.ITEM_MATERIAL_CHANCE
,ITEM_AFFIX_BASE_CHANCE
,ITEM_AFFIX_TIER_BONUS
: Control the likelihood of items having special materials or magical suffixes (e.g., "of Fiery Doom").
Hero Actions & Events
The probabilities and parameters governing what heroes do and what happens to them.
- Constants for resting (e.g.,
HERO_REST_LONG_CHANCE
,HERO_REST_SHORT_HP_PCT_TRIGGER
). NEMESIS_ENCOUNTER_BASE_CHANCE
,NEMESIS_ENCOUNTER_TIER_BONUS_FACTOR
: Control the appearance rate of powerful Nemesis monsters.- Probabilities for various quest event outcomes (e.g.,
QUEST_EVENT_MIRACULOUS_ROLL_MAX
,QUEST_EVENT_SETBACK_ROLL_MAX
,QUEST_EVENT_COMBAT_ROLL_MAX
). - Chances for finding items or gold during exploration/foraging activities (e.g.,
EXPLORE_FIND_CHANCE
,FORAGE_GOLD_VS_POTION_CHANCE
). - Specific constants for the newer "chore" actions (e.g.,
TEND_LANDMARK_GOLD_CHANCE
,GATHER_TALES_RUMOR_CHANCE
,CRAFT_ITEM_SUCCESS_CHANCE
,STUDY_MAP_DECIPHER_CHANCE
,OBSERVE_MISHAP_CHANCE
). These actions provide alternative ways to gain XP and gold, and interact with the world. - Breakthrough chances during training (
PRACTICE_WEAPON_STAT_BREAKTHROUGH_CHANCE
,STUDY_TOME_INT_BREAKTHROUGH_CHANCE
). - Chances for very rare positive or negative events (
ULTRA_RARE_LEVEL_BOOST_CHANCE
,PRAYER_FATALITY_CHANCE
,RARE_GUARDIAN_ENCOUNTER_CHANCE
).
Generational & World
Settings that affect the long-term arc of the saga and its flavor.
HONORIFIC_INHERITANCE_CHANCE
: The probability that an heir will receive an honorific title based on their parent's dominant stats.GLOBAL_FLAVOR_EVENT_CHANCE
: The per-tick chance of a random world flavor event occurring, drawn from theGLOBAL_FLAVOR_EVENTS
list.GENERATIONS_PER_EPOCH
: The number of generations that must pass within an epoch before an Epochal Shift occurs, ushering in a new age.
Modifying Procedural Content (Lexicons)
Beyond numerical constants, a significant portion of the game's unique flavor comes from large Python lists that serve as lexicons for procedural generation. These are found directly in the script:
- Naming Components:
HERO_NAMES_PREFIX
,HERO_NAMES_SUFFIX
,ADJECTIVES_GENERAL
,ADJECTIVES_ITEM_PREFIX
,ADJECTIVES_ITEM_SUFFIX
,NOUN_SUFFIXES_PLACES
,NOUN_SUFFIXES_ITEMS_WEAPON
(and Armor, Magic). Editing these allows you to change the pool of names for heroes, places, and items. - Item Properties:
ITEM_QUALITIES
,ITEM_MATERIALS
. Add or change these to introduce new tiers of item power or unique material compositions. - Creature Variety:
CREATURE_TYPES
. Expanding this list introduces new base monsters into the world. - Quest Content:
QUEST_VERBS
,QUEST_OBJECTIVES
. Modify these to change the nature and goals of generated quests. - Flavor & Lore:
HONORIFICS_BY_STAT
(the actual titles),GLOBAL_FLAVOR_EVENTS
(the text of world events),EPOCH_NAMES
(names for new ages),LANDMARK_TYPES_GENERIC
and related lists for the "Tend Local Landmark" action,TALE_SUBJECTS_GENERIC
and related lists for the "Share Tales" action, etc. Customizing these can deeply personalize the narrative feel of your saga.
When editing these lists, simply add or remove string entries following the existing Python list syntax.
Customizing Log Display via Script (Default Values)
While command-line arguments (--log-lines
and --log-width
, see Basic Command-Line Customizations) are recommended for temporary changes to the log display, you can also change the default values directly in the script by editing these constants:
- Edit
MAX_LOG_LINES
(script default: 25). - Edit
LOG_LINE_MAX_WIDTH
(script default: 84 characters; 0 means unlimited width).
A small note on script formatting: The Python script is formatted using Ruff for code consistency. This means some lines, especially comments alongside configuration variables at the top of the file, might be wrapped or adjusted by the formatter to maintain a standard line length.
Smoke Tests Methodology & Results
The "Smoke Test Mode" is a crucial diagnostic tool for this project, allowing for the simulation of vast amounts of game time at hyper-speed. It's primarily used by the author for development and pre-release stability checking but can be enabled by advanced users if they wish to perform their own stress tests (by setting SMOKE_TEST_MODE = True
in the script).
Why use Smoke Tests? (Methodology)
This mode serves to:
- Test the core game logic for stability over extremely long durations (billions of ticks).
- Identify potential bugs, unexpected interactions, or irregularities in progression that might only manifest after vast amounts of game time.
- Verify the long-term viability of the generational system and ensure numerical stability (i.e., numbers don't grow to problematic sizes).
- Assess resource consumption (like memory usage) under sustained, high-speed operation.
During a smoke test:
GAME_TICK_DELAY
is set to0
for maximum speed.PROGRESSION_RATE
is significantly increased (viaSMOKE_TEST_PROGRESSION_RATE
).- ANSI color codes are disabled, and screen clearing is skipped.
- Periodic progress reports are printed to the console.
- Game saving is disabled.
The author strives to conduct extensive smoke tests, often several hours long, before each release. While unit tests might cover individual components, these smoke tests provide confidence in the overall system's endurance and the integrity of a long-running saga.
Latest Smoke Test Results (version `1.0.0`)
- Wall Clock Run Time: 14h 9m 6s
- Total Ticks Run (Simulated In-Game Time): 1,773,576,995 (equivalent to over 56 years of in-game time with
GAME_TICK_DELAY
were 1.0 second) - Epochs Reached: 311
- Total Generations Passed: 1,551,010
- Peak RAM Usage: Less than 21MB (20,912 KB, measured via
time -v
) - Test Platform: Fedora Silverblue with Python 3.13.3
- Game Settings for Test (effective during smoke mode): Default internal smoke test settings (
GAME_TICK_DELAY = 0
, massively increasedPROGRESSION_RATE
, etc.).
---
Other Nyxatar Heroes Saga pages: