Slay the Spire path node data#

class BaseNode(parser: FileParser, *extra)[source]#

This the common base class for all path nodes, including Neow.

This provides basic utility functions that subclasses may use.

This also has abstract methods and properties that need to be overridden.

Subclasses can - and should - implement their own get_description method. This takes one argument, type collections.defaultdict[int, list[str]], and should modify that mapping in-place. Returning any non-None value will raise an error. The method should NOT attempt to call the superclass version of it with super(). BaseNode’s description method walks through the entire superclass tree, including third-party classes, in Method Resolution Order, and calls each existing get_description method in each class. Failure to implement this method in a direct subclass will raise an error, though additional classes in the MRO without one will pass silently.

Built-in index keys all use even numbers. Result will be joined together with newlines, and returned in ascending order. Custom code should only add data to odd indices. Ranges are provided here; refer to the relevant subclass for details. Calling order between various methods is not guaranteed - appending to a key already used may have unexpected results.

0 - Basic stuff; only for things that all nodes share
2 - Event-specific combat setup
4 - Combat results (damage taken, turns elapsed, etc.)
6 - Unique values (key obtained, campfire option, etc.)
8 - Neow bonus
10-20 - Potion usage data
30-36 - Relic obtention data
40-62 - Event results
70-78 - Shop contents
100+ - Special stuff; reserved for bugged or modded content
room_type: str = ''#

The display name of map nodes.

end_of_act: bool = False#

Whether to add a newline after this map node.

current_hp: int#

The current HP when exiting the node.

max_hp: int#

The max HP when exiting the node.

gold: int#

The gold when exiting the node.

floor: int#

The floor associated with this node.

card_count: int#

How many cards we currently have.

relic_count: int#

How many relics we currently have.

potion_count: int#

How many potions we currently have.

fights_count: int#

How many fights were fought so far this run.

turns_count: int#

How many turns passed so far this run.

floor_time: int#

How much time, in seconds, we spent on this floor.

property potions: list[Potion]#

Potions obtained on this node.

property picked: list[SingleCard]#

Cards picked this floor.

property skipped: list[SingleCard]#

Cards skipped this floor.

property cards_obtained: list[SingleCard]#

Cards obtained outside of a card reward this floor.

property cards_removed: list[SingleCard]#

Cards that were removed this floor.

property cards_transformed: list[SingleCard]#

Cards that were transformed away this floor.

property cards_upgraded: list[SingleCard]#

Cards that were upgraded this floor, before the upgrade.

property relics: list[Relic]#

Relics obtained on this floor.

property relics_lost: list[Relic]#

Relics lost on this floor.

property used_potions: list[Potion]#

Potions used on this floor.

property potions_from_alchemize: list[Potion]#

Potions obtained through Alchemize on this floor.

property potions_from_entropic: list[Potion]#

Potions obtained through Entropic Brew on this floor.

property discarded_potions: list[Potion]#

Potions which were mercilessly discarded on this floor.

property all_potions_received: list[Potion]#

All potions which were received on this floor.

property all_potions_dropped: list[Potion]#

All potions which were used or discarded this floor.

property skipped_relics: list[Relic]#

List of relics that were offered but skipped here.

property skipped_potions: list[Potion]#

List of potions that were offered but skipped here.

property name: str#

The name to display for the node.

card_delta() int[source]#

How many cards were added or removed on this floor.

relic_delta() int[source]#

How many relics were gained or lost on this floor.

potion_delta() int[source]#

How many potions were obtained, used, or discarded on this floor.

fights_delta() int[source]#

How many fights were fought on this floor.

turns_delta() int[source]#

How many turns were spent on this floor.

description() str[source]#

Return a newline-separated description for the current node.

Refer to BaseNode’s docstring for implementation details.

escaped_description() str[source]#

Return a description suitable for HTML pages.

get_description(to_append: dict[int, list[str]])[source]#

Add each individual node’s description, as needed.

class NeowBonus(parser: FileParser, *extra)[source]#

Bases: BaseNode

This class handles everything to do with the Neow bonus. Some of the run-specific data will only be available if RunHistoryPlus is installed when the run is first started. In the absence of the mod, sane defaults will be used.

floor: int = 0#

The floor associated with this node.

property name: str#

The name to display for the node.

property choice_made: bool#

Whether a Neow bonus was picked yet.

property boon_picked: str#

Which Neow bonus was picked, in a human-readable format.

property boons_skipped: Generator[str, None, None]#

Which Neow bonuses were skipped, in a human-readable format.

property cards_obtained: list[SingleCard]#

Cards obtained outside of a card reward this floor.

property cards_removed: list[SingleCard]#

Cards that were removed this floor.

property cards_transformed: list[SingleCard]#

Cards that were transformed away this floor.

property cards_upgraded: list[SingleCard]#

Cards that were upgraded this floor, before the upgrade.

property relics: list[Relic]#

Relics obtained on this floor.

property damage_taken: int#

How much damage we took here.

property max_hp_gained: int#

How much max HP we gained here.

property max_hp_lost: int#

How much max HP we lost here.

property current_hp: int#
property max_hp: int#
property gold: int#
get_cards() list[SingleCard][source]#

Return the cards we begin the run with.

bonus_THREE_CARDS() str[source]#

Call if the bonus is a draft of three cards, colorless or otherwise.

Raises:

ValueError – If no matching card choice can be found

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_RANDOM_COLORLESS() str#

Call if the bonus is a draft of three cards, colorless or otherwise.

Raises:

ValueError – If no matching card choice can be found

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_RANDOM_COMMON_RELIC() str[source]#

Call if the bonus is a random common relic.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_REMOVE_CARD() str[source]#

Call if the bonus is a card removal.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_TRANSFORM_CARD() str[source]#

Call if the bonus is a card transform.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_UPGRADE_CARD() str[source]#

Call if the bonus is a card upgrade.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_THREE_ENEMY_KILL() str[source]#

Call if the bonus is Neow’s Lament.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_THREE_SMALL_POTIONS() str[source]#

Call if the bonus is three potions.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_TEN_PERCENT_HP_BONUS() str[source]#

Call if the bonus is +10% Max HP.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_ONE_RANDOM_RARE_CARD() str[source]#

Call if the bonus is a random rare card.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_TWO_FIFTY_GOLD() str[source]#

Call if the bonus is 250 gold.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_TWENTY_PERCENT_HP_BONUS() str[source]#

Call if the bonus is +20% Max HP.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_RANDOM_COLORLESS_2() str#

Call if the bonus is a draft of three cards, colorless or otherwise.

Raises:

ValueError – If no matching card choice can be found

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_THREE_RARE_CARDS() str#

Call if the bonus is a draft of three cards, colorless or otherwise.

Raises:

ValueError – If no matching card choice can be found

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_REMOVE_TWO() str[source]#

Call if the bonus is two card removals.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_TRANSFORM_TWO_CARDS() str[source]#

Call if the bonus is two card transforms.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_ONE_RARE_RELIC() str[source]#

Call if the bonus is a random rare relic.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_BOSS_RELIC() str[source]#

Call if the bonus is swap your starter relic for a random boss relic.

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_CHOOSE_OTHER_CHAR_RANDOM_COMMON_CARD() str#

Call if the bonus is a draft of three cards, colorless or otherwise.

Raises:

ValueError – If no matching card choice can be found

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_CHOOSE_OTHER_CHAR_RANDOM_UNCOMMON_CARD() str#

Call if the bonus is a draft of three cards, colorless or otherwise.

Raises:

ValueError – If no matching card choice can be found

Returns:

Human-readable string to be used by as_str()

Return type:

str

bonus_CHOOSE_OTHER_CHAR_RANDOM_RARE_CARD() str#

Call if the bonus is a draft of three cards, colorless or otherwise.

Raises:

ValueError – If no matching card choice can be found

Returns:

Human-readable string to be used by as_str()

Return type:

str

cost_CURSE() str[source]#

Call if the cost is gain a random curse.

Returns:

Human-readable string to be used by as_str()

Return type:

str

cost_NO_GOLD() str[source]#

Call if the cost is lose all gold.

Returns:

Human-readable string to be used by as_str()

Return type:

str

cost_TEN_PERCENT_HP_LOSS() str[source]#

Call if the cost is -10% Max HP.

Returns:

Human-readable string to be used by as_str()

Return type:

str

cost_PERCENT_DAMAGE() str[source]#

Call if the cost is ~30% current HP loss.

Returns:

Human-readable string to be used by as_str()

Return type:

str

get_description(to_append: dict[int, list[str]])[source]#

Add each individual node’s description, as needed.

as_str() str[source]#

Get the Neow bonus information.

Returns:

Human-readable string of the cost and bonus.

Return type:

str

property has_info: bool#

Whether we support the bonus gotten.

property cards: list[CardData]#

Cards we have, in an iterable format.

card_delta() int[source]#

How many cards were added or removed on this floor.

relic_delta() int[source]#

How many relics were gained or lost on this floor.

property card_count: int#

How many cards we currently have.

property relic_count: int#

How many relics we currently have.

property potion_count: int#

How many potions we currently have.

property fights_count: int#

How many fights were fought so far this run.

property turns_count: int#

How many turns passed so far this run.

class NodeData(parser: FileParser, floor: int, *extra)[source]#

Bases: BaseNode

Contain relevant information for Spire nodes.

To instantiate a subclass, call the class with a FileParser instance (either src.runs.RunParser or src.save.Savefile) and the floor number.

To change behaviour, you need to subclass the relevant subclass and alter the behaviour there. Some features rely on objects being instances of specific NodeData subclasses (e.g. Treasure) and will fail otherwise. There is no mechanism currently for overriding which subclasses are returned by the node path parser.

map_icon = ''#

The map icon as present under the static/icons/ folder

description() str[source]#

Return a newline-separated description for the current node.

Refer to BaseNode’s docstring for implementation details.

get_description(to_append: dict[int, list[str]])[source]#

Add each individual node’s description, as needed.

class EncounterBase(parser: FileParser, floor: int, *extra)[source]#

Bases: NodeData

A base data class for Spire node encounters.

get_description(to_append: dict[int, list[str]])[source]#

Add each individual node’s description, as needed.

fights_delta() int[source]#

How many fights were fought on this floor.

turns_delta() int[source]#

How many turns were spent on this floor.

property name: str#

The name to display for the node.

property fought: str#

A human-readable name of the battle fought this floor.

property damage: int#

How much damage was taken this fight.

class NormalEncounter(parser: FileParser, floor: int, *extra)[source]#

Bases: EncounterBase

room_type: str = 'Enemy'#

The display name of map nodes.

map_icon = 'fight_normal.png'#

The map icon as present under the static/icons/ folder

class EventEncounter(parser: FileParser, floor: int, *extra)[source]#

Bases: EncounterBase

room_type: str = 'Unknown (Enemy)'#

The display name of map nodes.

map_icon = 'event_fight.png'#

The map icon as present under the static/icons/ folder

class EliteEncounter(parser: FileParser, floor: int, *extra)[source]#

Bases: EncounterBase

room_type: str = 'Elite'#

The display name of map nodes.

map_icon = 'fight_elite.png'#

The map icon as present under the static/icons/ folder

get_description(to_append: dict[int, list[str]])[source]#

Add each individual node’s description, as needed.

class EventElite(parser: FileParser, floor: int, *extra)[source]#

Bases: EliteEncounter

room_type: str = 'Unknown (Elite)'#

The display name of map nodes.

map_icon = 'event.png'#

The map icon as present under the static/icons/ folder

class Treasure(parser: FileParser, floor: int, *extra)[source]#

Bases: NodeData

room_type: str = 'Treasure'#

The display name of map nodes.

map_icon = 'treasure_chest.png'#

The map icon as present under the static/icons/ folder

key_relic: Relic | None#

The relic that was skipped for the Sapphire Key on this floor, if any.

blue_key: bool#

Whether we acquired the Sapphire Key on this floor.

get_description(to_append: dict[int, list[str]])[source]#

Add each individual node’s description, as needed.

class EventTreasure(parser: FileParser, floor: int, *extra)[source]#

Bases: Treasure

room_type: str = 'Unknown (Treasure)'#

The display name of map nodes.

map_icon = 'event_chest.png'#

The map icon as present under the static/icons/ folder

class Event(parser: FileParser, floor: int, event: dict[str, Any], *extra)[source]#

Bases: NodeData

room_type: str = 'Unknown'#

The display name of map nodes.

map_icon = 'event.png'#

The map icon as present under the static/icons/ folder

get_description(to_append: dict[int, list[str]])[source]#

Add each individual node’s description, as needed.

potion_delta() int[source]#

How many potions were obtained, used, or discarded on this floor.

property name: str#

The name to display for the node.

property choice: str#

Which option was picked for this event.

property damage_healed: int#

How much health was gained during this event.

property damage_taken: int#

How much health was lost during this event.

property max_hp_gained: int#

How much max HP was gained during this event.

property max_hp_lost: int#

How much max HP was lost during this event.

property gold_gained: int#

How much gold was gained during this event.

property gold_lost: int#

How much gold was lost during this event.

property cards_transformed: list[SingleCard]#

Cards that were transformed away this floor.

property cards_obtained: list[SingleCard]#

Cards obtained outside of a card reward this floor.

property cards_removed: list[SingleCard]#

Cards that were removed this floor.

property cards_upgraded: list[SingleCard]#

Cards that were upgraded this floor, before the upgrade.

property relics: list[Relic]#

Relics obtained on this floor.

property relics_lost: list[Relic]#

Relics lost on this floor.

class EventFight(parser: FileParser, floor: int, event: dict[str, Any], *extra)[source]#

Bases: Event, EncounterBase

This is a subclass for fights that happen in events.

This works for Dead Adventurer, Masked Bandits, etc. This does not work for the Colosseum fight (use Colosseum instead)

class Colosseum(parser: FileParser, floor: int, events: list[dict[str, Any]], *extra)[source]#

Bases: Event

get_description(to_append: dict[int, list[str]])[source]#

Add each individual node’s description, as needed.

property damage: int#

How much damage was taken over both fights, if relevant.

fights_delta() int[source]#

How many fights were fought on this floor.

turns_delta() int[source]#

How many turns were spent on this floor.

class Merchant(parser: FileParser, floor: int, *extra)[source]#

Bases: NodeData

room_type: str = 'Merchant'#

The display name of map nodes.

map_icon = 'shop.png'#

The map icon as present under the static/icons/ folder

contents: ShopContents#

The non-purchased contents of the shop.

bought: ShopContents#

All purchased goods from this shop.

purged: list[str]#

All cards removed this floor.

get_description(to_append: dict[int, list[str]])[source]#

Add each individual node’s description, as needed.

property picked: list[str]#

Cards picked this floor.

property relics: list[Relic]#

Relics obtained on this floor.

property potions: list[Potion]#

Potions obtained on this node.

card_delta() int[source]#

How many cards were added or removed on this floor.

class EventMerchant(parser: FileParser, floor: int, *extra)[source]#

Bases: Merchant

room_type: str = 'Unknown (Merchant)'#

The display name of map nodes.

map_icon = 'event_shop.png'#

The map icon as present under the static/icons/ folder

class ShopContents[source]#

Contains one floor’s shop contents.

This can be used either for contents or purchases.

add_card(card: str)[source]#

Add a card to this floor’s contents.

add_relic(relic: str)[source]#

Add a relic to this floor’s contents.

add_potion(potion: str)[source]#

Add a potion to this floor’s contents.

class Campfire(parser: FileParser, floor: int, *extra)[source]#

Bases: NodeData

room_type: str = 'Rest Site'#

The display name of map nodes.

map_icon = 'rest.png'#

The map icon as present under the static/icons/ folder

get_description(to_append: dict[int, list[str]]) str[source]#

Add each individual node’s description, as needed.

property action: str#

Human-readable string of the action taken on this floor.

class Boss(parser: FileParser, floor: int, *extra)[source]#

Bases: EncounterBase

room_type: str = 'Boss'#

The display name of map nodes.

map_icon = 'boss_node.png'#

The map icon as present under the static/icons/ folder

class BossChest(parser: FileParser, floor: int, *extra)[source]#

Bases: NodeData

room_type: str = 'Boss Chest'#

The display name of map nodes.

map_icon = 'boss_chest.png'#

The map icon as present under the static/icons/ folder

end_of_act: bool = True#

Whether to add a newline after this map node.

property relics: list[Relic]#

Relics obtained on this floor.

property skipped_relics: list[Relic]#

List of relics that were offered but skipped here.

class Act4Transition(parser: FileParser, floor: int, *extra)[source]#

Bases: NodeData

room_type: str = 'Transition into Act 4'#

The display name of map nodes.

map_icon = 'event.png'#

The map icon as present under the static/icons/ folder

end_of_act: bool = True#

Whether to add a newline after this map node.

class Victory(parser: FileParser, floor: int, *extra)[source]#

Bases: NodeData

room_type: str = 'Victory!'#

The display name of map nodes.

map_icon = 'event.png'#

The map icon as present under the static/icons/ folder

get_description(to_append: dict[int, list[str]])[source]#

Add each individual node’s description, as needed.

property score: int#

How many points we got this run.

property score_breakdown: list[str]#

Human-readable breakdown of the score.