//
// RogueMain.h
// Brogue
//
// Created by Brian Walker on 12/26/08.
// Copyright 2012. All rights reserved.
//
// This file is part of Brogue.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "PlatformDefines.h"
// unicode: comment this line to revert to ASCII
#define USE_UNICODE
// Brogue version: what the user sees in the menu and title
#define BROGUE_VERSION_STRING "CE 1.9.3" BROGUE_EXTRA_VERSION
// Recording version. Saved into recordings and save files made by this version.
// Cannot be longer than 16 chars
#define BROGUE_RECORDING_VERSION_STRING "CE 1.9.3"
/* Patch pattern. A scanf format string which matches an unsigned short. If this
matches against a recording version string, it defines a "patch version." During
normal play, rogue.patchVersion is set to the match of the game's recording
version above, or 0 if it doesn't match.
The game will only load a recording/save if either a) it has a patch version
which is equal or less than the patch version of the current game
(rogue.patchLevel is set to the recording's); or b) it doesn't match the version
strings, but they are equal (rogue.patchLevel is set to 0).
*/
#define BROGUE_PATCH_VERSION_PATTERN "CE 1.9.%hu"
// Dungeon version. Used in seed catalog output.
#define BROGUE_DUNGEON_VERSION_STRING "CE 1.9"
#define DEBUG if (rogue.wizard)
#define MONSTERS_ENABLED (!rogue.wizard || 1) // Quest room monsters can be generated regardless.
#define ITEMS_ENABLED (!rogue.wizard || 1)
#define D_BULLET_TIME (rogue.wizard && 0)
#define D_WORMHOLING (rogue.wizard && 1)
#define D_IMMORTAL (rogue.wizard && 1)
#define D_SAFETY_VISION (rogue.wizard && 0)
#define D_SCENT_VISION (rogue.wizard && 0)
#define D_DISABLE_BACKGROUND_COLORS (rogue.wizard && 0)
#define D_INSPECT_LEVELGEN (rogue.wizard && 0)
#define D_INSPECT_MACHINES (rogue.wizard && 0)
#define D_MESSAGE_ITEM_GENERATION (rogue.wizard && 0)
#define D_MESSAGE_MACHINE_GENERATION (rogue.wizard && 0)
// set to false to allow multiple loads from the same saved file:
#define DELETE_SAVE_FILE_AFTER_LOADING true
// set to false to disable references to keystrokes (e.g. for a tablet port)
#define KEYBOARD_LABELS true
//#define BROGUE_ASSERTS // introduces several assert()s -- useful to find certain array overruns and other bugs
//#define AUDIT_RNG // VERY slow, but sometimes necessary to debug out-of-sync recording errors
//#define GENERATE_FONT_FILES // Displays font in grid upon startup, which can be screen-captured into font files for PC.
#ifdef BROGUE_ASSERTS
#include <assert.h>
#define brogueAssert(x) assert(x)
#else
#define brogueAssert(x)
#endif
#define boolean char
#define false 0
#define true 1
#define Fl(N) ((unsigned long) 1 << (N))
typedef long long fixpt;
#define FP_BASE 16 // Don't change this without recalculating all of the power tables throughout the code!
#define FP_FACTOR (1LL << FP_BASE)
#define FP_MUL(x, y) ((x) * (y) / FP_FACTOR)
#define FP_DIV(x, y) ((x) * FP_FACTOR / (y))
// recording and save filenames
#define LAST_GAME_PATH "LastGame.broguesave"
#define LAST_GAME_NAME "LastGame"
#define LAST_RECORDING_NAME "LastRecording"
#define RECORDING_SUFFIX ".broguerec"
#define GAME_SUFFIX ".broguesave"
#define ANNOTATION_SUFFIX ".txt"
#define RNG_LOG "RNGLog.txt"
#define SCREENSHOT_SUFFIX ".png"
#define BROGUE_FILENAME_MAX (min(1024*4, FILENAME_MAX))
// Date format used when listing recordings and high scores
#define DATE_FORMAT "%Y-%m-%d" // see strftime() documentation
#define MESSAGE_LINES 3
#define MESSAGE_ARCHIVE_LINES ROWS
// Size of the entire terminal window. These need to be hard-coded here and in Viewport.h
#define COLS 100
#define ROWS (31 + MESSAGE_LINES)
// Size of the portion of the terminal window devoted to displaying the dungeon:
#define DCOLS (COLS - STAT_BAR_WIDTH - 1) // n columns on the left for the sidebar;
// one column to separate the sidebar from the map.
#define DROWS (ROWS - MESSAGE_LINES - 2) // n lines at the top for messages;
// one line at the bottom for flavor text;
// another line at the bottom for the menu bar.
#define STAT_BAR_WIDTH 20 // number of characters in the stats bar to the left of the map
#define LOS_SLOPE_GRANULARITY 32768 // how finely we divide up the squares when calculating slope;
// higher numbers mean fewer artifacts but more memory and processing
#define INTERFACE_OPACITY 95
#define LIGHT_SMOOTHING_THRESHOLD 150 // light components higher than this magnitude will be toned down a little
#define MAX_BOLT_LENGTH DCOLS*10
#define VISIBILITY_THRESHOLD 50 // how bright cumulative light has to be before the cell is marked visible
#define AMULET_LEVEL 26 // how deep before the amulet appears
#define DEEPEST_LEVEL 40 // how deep the universe goes
#define MACHINES_FACTOR FP_FACTOR // use this to adjust machine frequency
#define MACHINES_BUFFER_LENGTH 200
#define WEAPON_KILLS_TO_AUTO_ID 20
#define ARMOR_DELAY_TO_AUTO_ID 1000
#define RING_DELAY_TO_AUTO_ID 1500
#define FALL_DAMAGE_MIN 8
#define FALL_DAMAGE_MAX 10
#define INPUT_RECORD_BUFFER 1000 // how many bytes of input data to keep in memory before saving it to disk
#define DEFAULT_PLAYBACK_DELAY 50
#define HIGH_SCORES_COUNT 30
// color escapes
#define COLOR_ESCAPE 25
#define COLOR_VALUE_INTERCEPT 25
// display characters:
enum displayGlyph {
G_UP_ARROW = 128,
G_DOWN_ARROW,
G_POTION,
G_GRASS,
G_WALL,
G_DEMON,
G_OPEN_DOOR,
G_GOLD,
G_CLOSED_DOOR,
G_RUBBLE,
G_KEY,
G_BOG,
G_CHAIN_TOP_LEFT,
G_CHAIN_BOTTOM_RIGHT,
G_CHAIN_TOP_RIGHT,
G_CHAIN_BOTTOM_LEFT,
G_CHAIN_TOP,
G_CHAIN_BOTTOM,
G_CHAIN_LEFT,
G_CHAIN_RIGHT,
G_FOOD,
G_UP_STAIRS,
G_VENT,
G_DOWN_STAIRS,
G_PLAYER,
G_BOG_MONSTER,
G_CENTAUR,
G_DRAGON,
G_FLAMEDANCER,
G_GOLEM,
G_TENTACLE_HORROR,
G_IFRIT,
G_JELLY,
G_KRAKEN,
G_LICH,
G_NAGA,
G_OGRE,
G_PHANTOM,
G_REVENANT,
G_SALAMANDER,
G_TROLL,
G_UNDERWORM,
G_VAMPIRE,
G_WRAITH,
G_ZOMBIE,
G_ARMOR,
G_STAFF,
G_WEB,
G_MOUND,
G_BLOAT,
G_CENTIPEDE,
G_DAR_BLADEMASTER,
G_EEL,
G_FURY,
G_GOBLIN,
G_IMP,
G_JACKAL,
G_KOBOLD,
G_MONKEY,
G_PIXIE,
G_RAT,
G_SPIDER,
G_TOAD,
G_BAT,
G_WISP,
G_PHOENIX,
G_ALTAR,
G_LIQUID,
G_FLOOR,
G_CHASM,
G_TRAP,
G_FIRE,
G_FOLIAGE,
G_AMULET,
G_SCROLL,
G_RING,
G_WEAPON,
G_TURRET,
G_TOTEM,
G_GOOD_MAGIC,
G_BAD_MAGIC,
G_DOORWAY,
G_CHARM,
G_WALL_TOP,
G_DAR_PRIESTESS,
G_DAR_BATTLEMAGE,
G_GOBLIN_MAGIC,
G_GOBLIN_CHIEFTAN,
G_OGRE_MAGIC,
G_GUARDIAN,
G_WINGED_GUARDIAN,
G_EGG,
G_WARDEN,
G_DEWAR,
G_ANCIENT_SPIRIT,
G_LEVER,
G_LEVER_PULLED,
G_BLOODWORT_STALK,
G_FLOOR_ALT,
G_UNICORN,
G_GEM,
G_WAND,
G_GRANITE,
G_CARPET,
G_CLOSED_IRON_DOOR,
G_OPEN_IRON_DOOR,
G_TORCH,
G_CRYSTAL,
G_PORTCULLIS,
G_BARRICADE,
G_STATUE,
G_CRACKED_STATUE,
G_CLOSED_CAGE,
G_OPEN_CAGE,
G_PEDESTAL,
G_CLOSED_COFFIN,
G_OPEN_COFFIN,
G_MAGIC_GLYPH,
G_BRIDGE,
G_BONES,
G_ELECTRIC_CRYSTAL,
G_ASHES,
G_BEDROLL,
G_BLOODWORT_POD,
G_VINE,
G_NET,
G_LICHEN,
G_PIPES,
G_SAC_ALTAR,
G_ORB_ALTAR
};
enum eventTypes {
KEYSTROKE,
MOUSE_UP,
MOUSE_DOWN,
RIGHT_MOUSE_DOWN,
RIGHT_MOUSE_UP,
MOUSE_ENTERED_CELL,
RNG_CHECK,
SAVED_GAME_LOADED,
END_OF_RECORDING,
EVENT_ERROR,
NUMBER_OF_EVENT_TYPES, // unused
};
enum notificationEventTypes {
GAMEOVER_QUIT,
GAMEOVER_DEATH,
GAMEOVER_VICTORY,
GAMEOVER_SUPERVICTORY,
GAMEOVER_RECORDING
};
typedef struct rogueEvent {
enum eventTypes eventType;
signed long param1;
signed long param2;
boolean controlKey;
boolean shiftKey;
} rogueEvent;
typedef struct rogueHighScoresEntry {
signed long score;
char date[100];
char description[DCOLS];
} rogueHighScoresEntry;
typedef struct fileEntry {
char *path;
struct tm date;
} fileEntry;
enum RNGs {
RNG_SUBSTANTIVE,
RNG_COSMETIC,
NUMBER_OF_RNGS,
};
enum displayDetailValues {
DV_UNLIT = 0,
DV_LIT,
DV_DARK,
};
enum directions {
NO_DIRECTION = -1,
// Cardinal directions; must be 0-3:
UP = 0,
DOWN = 1,
LEFT = 2,
RIGHT = 3,
// Secondary directions; must be 4-7:
UPLEFT = 4,
DOWNLEFT = 5,
UPRIGHT = 6,
DOWNRIGHT = 7,
DIRECTION_COUNT = 8,
};
enum textEntryTypes {
TEXT_INPUT_NORMAL = 0,
TEXT_INPUT_FILENAME,
TEXT_INPUT_NUMBERS,
TEXT_INPUT_TYPES,
};
#define NUMBER_DYNAMIC_COLORS 6
enum tileType {
NOTHING = 0,
GRANITE,
FLOOR,
FLOOR_FLOODABLE,
CARPET,
MARBLE_FLOOR,
WALL,
DOOR,
OPEN_DOOR,
SECRET_DOOR,
LOCKED_DOOR,
OPEN_IRON_DOOR_INERT,
DOWN_STAIRS,
UP_STAIRS,
DUNGEON_EXIT,
DUNGEON_PORTAL,
TORCH_WALL, // wall lit with a torch
CRYSTAL_WALL,
PORTCULLIS_CLOSED,
PORTCULLIS_DORMANT,
WOODEN_BARRICADE,
PILOT_LIGHT_DORMANT,
PILOT_LIGHT,
HAUNTED_TORCH_DORMANT,
HAUNTED_TORCH_TRANSITIONING,
HAUNTED_TORCH,
WALL_LEVER_HIDDEN,
WALL_LEVER,
WALL_LEVER_PULLED,
WALL_LEVER_HIDDEN_DORMANT,
STATUE_INERT,
STATUE_DORMANT,
STATUE_CRACKING,
STATUE_INSTACRACK,
PORTAL,
TURRET_DORMANT,
WALL_MONSTER_DORMANT,
DARK_FLOOR_DORMANT,
DARK_FLOOR_DARKENING,
DARK_FLOOR,
MACHINE_TRIGGER_FLOOR,
ALTAR_INERT,
ALTAR_KEYHOLE,
ALTAR_CAGE_OPEN,
ALTAR_CAGE_CLOSED,
ALTAR_SWITCH,
ALTAR_SWITCH_RETRACTING,
ALTAR_CAGE_RETRACTABLE,
PEDESTAL,
MONSTER_CAGE_OPEN,
MONSTER_CAGE_CLOSED,
COFFIN_CLOSED,
COFFIN_OPEN,
GAS_TRAP_POISON_HIDDEN,
GAS_TRAP_POISON,
TRAP_DOOR_HIDDEN,
TRAP_DOOR,
GAS_TRAP_PARALYSIS_HIDDEN,
GAS_TRAP_PARALYSIS,
MACHINE_PARALYSIS_VENT_HIDDEN,
MACHINE_PARALYSIS_VENT,
GAS_TRAP_CONFUSION_HIDDEN,
GAS_TRAP_CONFUSION,
FLAMETHROWER_HIDDEN,
FLAMETHROWER,
FLOOD_TRAP_HIDDEN,
FLOOD_TRAP,
NET_TRAP_HIDDEN,
NET_TRAP,
ALARM_TRAP_HIDDEN,
ALARM_TRAP,
MACHINE_POISON_GAS_VENT_HIDDEN,
MACHINE_POISON_GAS_VENT_DORMANT,
MACHINE_POISON_GAS_VENT,
MACHINE_METHANE_VENT_HIDDEN,
MACHINE_METHANE_VENT_DORMANT,
MACHINE_METHANE_VENT,
STEAM_VENT,
MACHINE_PRESSURE_PLATE,
MACHINE_PRESSURE_PLATE_USED,
MACHINE_GLYPH,
MACHINE_GLYPH_INACTIVE,
DEWAR_CAUSTIC_GAS,
DEWAR_CONFUSION_GAS,
DEWAR_PARALYSIS_GAS,
DEWAR_METHANE_GAS,
DEEP_WATER,
SHALLOW_WATER,
MUD,
CHASM,
CHASM_EDGE,
MACHINE_COLLAPSE_EDGE_DORMANT,
MACHINE_COLLAPSE_EDGE_SPREADING,
LAVA,
LAVA_RETRACTABLE,
LAVA_RETRACTING,
SUNLIGHT_POOL,
DARKNESS_PATCH,
ACTIVE_BRIMSTONE,
INERT_BRIMSTONE,
OBSIDIAN,
BRIDGE,
BRIDGE_FALLING,
BRIDGE_EDGE,
STONE_BRIDGE,
MACHINE_FLOOD_WATER_DORMANT,
MACHINE_FLOOD_WATER_SPREADING,
MACHINE_MUD_DORMANT,
ICE_DEEP,
ICE_DEEP_MELT,
ICE_SHALLOW,
ICE_SHALLOW_MELT,
HOLE,
HOLE_GLOW,
HOLE_EDGE,
FLOOD_WATER_DEEP,
FLOOD_WATER_SHALLOW,
GRASS,
DEAD_GRASS,
GRAY_FUNGUS,
LUMINESCENT_FUNGUS,
LICHEN,
HAY,
RED_BLOOD,
GREEN_BLOOD,
PURPLE_BLOOD,
ACID_SPLATTER,
VOMIT,
URINE,
UNICORN_POOP,
WORM_BLOOD,
ASH,
BURNED_CARPET,
PUDDLE,
BONES,
RUBBLE,
JUNK,
BROKEN_GLASS,
ECTOPLASM,
EMBERS,
SPIDERWEB,
NETTING,
FOLIAGE,
DEAD_FOLIAGE,
TRAMPLED_FOLIAGE,
FUNGUS_FOREST,
TRAMPLED_FUNGUS_FOREST,
FORCEFIELD,
FORCEFIELD_MELT,
SACRED_GLYPH,
MANACLE_TL,
MANACLE_BR,
MANACLE_TR,
MANACLE_BL,
MANACLE_T,
MANACLE_B,
MANACLE_L,
MANACLE_R,
PORTAL_LIGHT,
GUARDIAN_GLOW,
PLAIN_FIRE,
BRIMSTONE_FIRE,
FLAMEDANCER_FIRE,
GAS_FIRE,
GAS_EXPLOSION,
DART_EXPLOSION,
ITEM_FIRE,
CREATURE_FIRE,
POISON_GAS,
CONFUSION_GAS,
ROT_GAS,
STENCH_SMOKE_GAS,
PARALYSIS_GAS,
METHANE_GAS,
STEAM,
DARKNESS_CLOUD,
HEALING_CLOUD,
BLOODFLOWER_STALK,
BLOODFLOWER_POD,
HAVEN_BEDROLL,
DEEP_WATER_ALGAE_WELL,
DEEP_WATER_ALGAE_1,
DEEP_WATER_ALGAE_2,
ANCIENT_SPIRIT_VINES,
ANCIENT_SPIRIT_GRASS,
AMULET_SWITCH,
COMMUTATION_ALTAR,
COMMUTATION_ALTAR_INERT,
PIPE_GLOWING,
PIPE_INERT,
RESURRECTION_ALTAR,
RESURRECTION_ALTAR_INERT,
MACHINE_TRIGGER_FLOOR_REPEATING,
SACRIFICE_ALTAR_DORMANT,
SACRIFICE_ALTAR,
SACRIFICE_LAVA,
SACRIFICE_CAGE_DORMANT,
DEMONIC_STATUE,
STATUE_INERT_DOORWAY,
STATUE_DORMANT_DOORWAY,
CHASM_WITH_HIDDEN_BRIDGE,
CHASM_WITH_HIDDEN_BRIDGE_ACTIVE,
MACHINE_CHASM_EDGE,
RAT_TRAP_WALL_DORMANT,
RAT_TRAP_WALL_CRACKING,
ELECTRIC_CRYSTAL_OFF,
ELECTRIC_CRYSTAL_ON,
TURRET_LEVER,
WORM_TUNNEL_MARKER_DORMANT,
WORM_TUNNEL_MARKER_ACTIVE,
WORM_TUNNEL_OUTER_WALL,
BRAZIER,
MUD_FLOOR,
MUD_WALL,
MUD_DOORWAY,
NUMBER_TILETYPES,
};
enum lightType {
NO_LIGHT,
MINERS_LIGHT,
BURNING_CREATURE_LIGHT,
WISP_LIGHT,
SALAMANDER_LIGHT,
IMP_LIGHT,
PIXIE_LIGHT,
LICH_LIGHT,
FLAMEDANCER_LIGHT,
SENTINEL_LIGHT,
UNICORN_LIGHT,
IFRIT_LIGHT,
PHOENIX_LIGHT,
PHOENIX_EGG_LIGHT,
YENDOR_LIGHT,
SPECTRAL_BLADE_LIGHT,
SPECTRAL_IMAGE_LIGHT,
SPARK_TURRET_LIGHT,
EXPLOSIVE_BLOAT_LIGHT,
BOLT_LIGHT_SOURCE,
TELEPATHY_LIGHT,
SACRIFICE_MARK_LIGHT,
SCROLL_PROTECTION_LIGHT,
SCROLL_ENCHANTMENT_LIGHT,
POTION_STRENGTH_LIGHT,
EMPOWERMENT_LIGHT,
GENERIC_FLASH_LIGHT,
FALLEN_TORCH_FLASH_LIGHT,
SUMMONING_FLASH_LIGHT,
EXPLOSION_FLARE_LIGHT,
QUIETUS_FLARE_LIGHT,
SLAYING_FLARE_LIGHT,
CHARGE_FLASH_LIGHT,
TORCH_LIGHT,
LAVA_LIGHT,
SUN_LIGHT,
DARKNESS_PATCH_LIGHT,
FUNGUS_LIGHT,
FUNGUS_FOREST_LIGHT,
LUMINESCENT_ALGAE_BLUE_LIGHT,
LUMINESCENT_ALGAE_GREEN_LIGHT,
ECTOPLASM_LIGHT,
UNICORN_POOP_LIGHT,
EMBER_LIGHT,
FIRE_LIGHT,
BRIMSTONE_FIRE_LIGHT,
EXPLOSION_LIGHT,
INCENDIARY_DART_LIGHT,
PORTAL_ACTIVATE_LIGHT,
CONFUSION_GAS_LIGHT,
DARKNESS_CLOUD_LIGHT,
FORCEFIELD_LIGHT,
CRYSTAL_WALL_LIGHT,
CANDLE_LIGHT,
HAUNTED_TORCH_LIGHT,
GLYPH_LIGHT_DIM,
GLYPH_LIGHT_BRIGHT,
SACRED_GLYPH_LIGHT,
DESCENT_LIGHT,
DEMONIC_STATUE_LIGHT,
NUMBER_LIGHT_KINDS
};
#define NUMBER_ITEM_CATEGORIES 13
// Item categories
enum itemCategory {
FOOD = Fl(0),
WEAPON = Fl(1),
ARMOR = Fl(2),
POTION = Fl(3),
SCROLL = Fl(4),
STAFF = Fl(5),
WAND = Fl(6),
RING = Fl(7),
CHARM = Fl(8),
GOLD = Fl(9),
AMULET = Fl(10),
GEM = Fl(11),
KEY = Fl(12),
CAN_BE_DETECTED = (WEAPON | ARMOR | POTION | SCROLL | RING | CHARM | WAND | STAFF | AMULET),
PRENAMED_CATEGORY = (FOOD | GOLD | AMULET | GEM | KEY),
NEVER_IDENTIFIABLE = (FOOD | CHARM | GOLD | AMULET | GEM | KEY),
CAN_BE_SWAPPED = (WEAPON | ARMOR | STAFF | CHARM | RING),
ALL_ITEMS = (FOOD|POTION|WEAPON|ARMOR|STAFF|WAND|SCROLL|RING|CHARM|GOLD|AMULET|GEM|KEY),
};
enum keyKind {
KEY_DOOR,
KEY_CAGE,
KEY_PORTAL,
NUMBER_KEY_TYPES
};
enum foodKind {
RATION,
FRUIT,
NUMBER_FOOD_KINDS
};
enum potionKind {
POTION_LIFE,
POTION_STRENGTH,
POTION_TELEPATHY,
POTION_LEVITATION,
POTION_DETECT_MAGIC,
POTION_HASTE_SELF,
POTION_FIRE_IMMUNITY,
POTION_INVISIBILITY,
POTION_POISON,
POTION_PARALYSIS,
POTION_HALLUCINATION,
POTION_CONFUSION,
POTION_INCINERATION,
POTION_DARKNESS,
POTION_DESCENT,
POTION_LICHEN,
NUMBER_POTION_KINDS
};
enum weaponKind {
DAGGER,
SWORD,
BROADSWORD,
WHIP,
RAPIER,
FLAIL,
MACE,
HAMMER,
SPEAR,
PIKE,
AXE,
WAR_AXE,
DART,
INCENDIARY_DART,
JAVELIN,
NUMBER_WEAPON_KINDS
};
enum weaponEnchants {
W_SPEED,
W_QUIETUS,
W_PARALYSIS,
W_MULTIPLICITY,
W_SLOWING,
W_CONFUSION,
W_FORCE,
W_SLAYING,
W_MERCY,
NUMBER_GOOD_WEAPON_ENCHANT_KINDS = W_MERCY,
W_PLENTY,
NUMBER_WEAPON_RUNIC_KINDS
};
enum armorKind {
LEATHER_ARMOR,
SCALE_MAIL,
CHAIN_MAIL,
BANDED_MAIL,
SPLINT_MAIL,
PLATE_MAIL,
NUMBER_ARMOR_KINDS
};
enum armorEnchants {
A_MULTIPLICITY,
A_MUTUALITY,
A_ABSORPTION,
A_REPRISAL,
A_IMMUNITY,
A_REFLECTION,
A_RESPIRATION,
A_DAMPENING,
A_BURDEN,
NUMBER_GOOD_ARMOR_ENCHANT_KINDS = A_BURDEN,
A_VULNERABILITY,
A_IMMOLATION,
NUMBER_ARMOR_ENCHANT_KINDS,
};
enum wandKind {
WAND_TELEPORT,
WAND_SLOW,
WAND_POLYMORPH,
WAND_NEGATION,
WAND_DOMINATION,
WAND_BECKONING,
WAND_PLENTY,
WAND_INVISIBILITY,
WAND_EMPOWERMENT,
NUMBER_WAND_KINDS
};
enum staffKind {
STAFF_LIGHTNING,
STAFF_FIRE,
STAFF_POISON,
STAFF_TUNNELING,
STAFF_BLINKING,
STAFF_ENTRANCEMENT,
STAFF_OBSTRUCTION,
STAFF_DISCORD,
STAFF_CONJURATION,
STAFF_HEALING,
STAFF_HASTE,
STAFF_PROTECTION,
NUMBER_STAFF_KINDS
};
// these must be wand bolts, in order, and then staff bolts, in order:
enum boltType {
BOLT_NONE = 0,
BOLT_TELEPORT,
BOLT_SLOW,
BOLT_POLYMORPH,
BOLT_NEGATION,
BOLT_DOMINATION,
BOLT_BECKONING,
BOLT_PLENTY,
BOLT_INVISIBILITY,
BOLT_EMPOWERMENT,
BOLT_LIGHTNING,
BOLT_FIRE,
BOLT_POISON,
BOLT_TUNNELING,
BOLT_BLINKING,
BOLT_ENTRANCEMENT,
BOLT_OBSTRUCTION,
BOLT_DISCORD,
BOLT_CONJURATION,
BOLT_HEALING,
BOLT_HASTE,
BOLT_SLOW_2,
BOLT_SHIELDING,
BOLT_SPIDERWEB,
BOLT_SPARK,
BOLT_DRAGONFIRE,
BOLT_DISTANCE_ATTACK,
BOLT_POISON_DART,
BOLT_ANCIENT_SPIRIT_VINES,
BOLT_WHIP,
NUMBER_BOLT_KINDS
};
enum ringKind {
RING_CLAIRVOYANCE,
RING_STEALTH,
RING_REGENERATION,
RING_TRANSFERENCE,
RING_LIGHT,
RING_AWARENESS,
RING_WISDOM,
RING_REAPING,
NUMBER_RING_KINDS
};
enum charmKind {
CHARM_HEALTH,
CHARM_PROTECTION,
CHARM_HASTE,
CHARM_FIRE_IMMUNITY,
CHARM_INVISIBILITY,
CHARM_TELEPATHY,
CHARM_LEVITATION,
CHARM_SHATTERING,
CHARM_GUARDIAN,
CHARM_TELEPORTATION,
CHARM_RECHARGING,
CHARM_NEGATION,
NUMBER_CHARM_KINDS
};
enum scrollKind {
SCROLL_ENCHANTING,
SCROLL_IDENTIFY,
SCROLL_TELEPORT,
SCROLL_REMOVE_CURSE,
SCROLL_RECHARGING,
SCROLL_PROTECT_ARMOR,
SCROLL_PROTECT_WEAPON,
SCROLL_SANCTUARY,
SCROLL_MAGIC_MAPPING,
SCROLL_NEGATION,
SCROLL_SHATTERING,
SCROLL_DISCORD,
SCROLL_AGGRAVATE_MONSTER,
SCROLL_SUMMON_MONSTER,
NUMBER_SCROLL_KINDS
};
#define MAX_PACK_ITEMS 26
enum monsterTypes {
MK_YOU,
MK_RAT,
MK_KOBOLD,
MK_JACKAL,
MK_EEL,
MK_MONKEY,
MK_BLOAT,
MK_PIT_BLOAT,
MK_GOBLIN,
MK_GOBLIN_CONJURER,
MK_GOBLIN_MYSTIC,
MK_GOBLIN_TOTEM,
MK_PINK_JELLY,
MK_TOAD,
MK_VAMPIRE_BAT,
MK_ARROW_TURRET,
MK_ACID_MOUND,
MK_CENTIPEDE,
MK_OGRE,
MK_BOG_MONSTER,
MK_OGRE_TOTEM,
MK_SPIDER,
MK_SPARK_TURRET,
MK_WILL_O_THE_WISP,
MK_WRAITH,
MK_ZOMBIE,
MK_TROLL,
MK_OGRE_SHAMAN,
MK_NAGA,
MK_SALAMANDER,
MK_EXPLOSIVE_BLOAT,
MK_DAR_BLADEMASTER,
MK_DAR_PRIESTESS,
MK_DAR_BATTLEMAGE,
MK_ACID_JELLY,
MK_CENTAUR,
MK_UNDERWORM,
MK_SENTINEL,
MK_DART_TURRET,
MK_KRAKEN,
MK_LICH,
MK_PHYLACTERY,
MK_PIXIE,
MK_PHANTOM,
MK_FLAME_TURRET,
MK_IMP,
MK_FURY,
MK_REVENANT,
MK_TENTACLE_HORROR,
MK_GOLEM,
MK_DRAGON,
MK_GOBLIN_CHIEFTAN,
MK_BLACK_JELLY,
MK_VAMPIRE,
MK_FLAMEDANCER,
MK_SPECTRAL_BLADE,
MK_SPECTRAL_IMAGE,
MK_GUARDIAN,
MK_WINGED_GUARDIAN,
MK_CHARM_GUARDIAN,
MK_WARDEN_OF_YENDOR,
MK_ELDRITCH_TOTEM,
MK_MIRRORED_TOTEM,
MK_UNICORN,
MK_IFRIT,
MK_PHOENIX,
MK_PHOENIX_EGG,
MK_ANCIENT_SPIRIT,
NUMBER_MONSTER_KINDS
};
#define NUMBER_MUTATORS 8
#define NUMBER_HORDES 177
#define MONSTER_CLASS_COUNT 15
// flavors
#define NUMBER_ITEM_COLORS 21
#define NUMBER_TITLE_PHONEMES 21
#define NUMBER_ITEM_WOODS 21
#define NUMBER_POTION_DESCRIPTIONS 18
#define NUMBER_ITEM_METALS 12
#define NUMBER_ITEM_GEMS 18
// Dungeon flags
enum tileFlags {
DISCOVERED = Fl(0),
VISIBLE = Fl(1), // cell has sufficient light and is in field of view, ready to draw.
HAS_PLAYER = Fl(2),
HAS_MONSTER = Fl(3),
HAS_DORMANT_MONSTER = Fl(4), // hidden monster on the square
HAS_ITEM = Fl(5),
IN_FIELD_OF_VIEW = Fl(6), // player has unobstructed line of sight whether or not there is enough light
WAS_VISIBLE = Fl(7),
HAS_STAIRS = Fl(8),
SEARCHED_FROM_HERE = Fl(9), // player already auto-searched here; can't auto-search here again
IS_IN_SHADOW = Fl(10), // so that a player gains an automatic stealth bonus
MAGIC_MAPPED = Fl(11),
ITEM_DETECTED = Fl(12),
CLAIRVOYANT_VISIBLE = Fl(13),
WAS_CLAIRVOYANT_VISIBLE = Fl(14),
CLAIRVOYANT_DARKENED = Fl(15), // magical blindness from a cursed ring of clairvoyance
CAUGHT_FIRE_THIS_TURN = Fl(16), // so that fire does not spread asymmetrically
PRESSURE_PLATE_DEPRESSED = Fl(17), // so that traps do not trigger repeatedly while you stand on them
STABLE_MEMORY = Fl(18), // redraws will be pulled from the memory array, not recalculated
KNOWN_TO_BE_TRAP_FREE = Fl(19), // keep track of where the player has stepped or watched monsters step as he knows no traps are there
IS_IN_PATH = Fl(20), // the yellow trail leading to the cursor
IN_LOOP = Fl(21), // this cell is part of a terrain loop
IS_CHOKEPOINT = Fl(22), // if this cell is blocked, part of the map will be rendered inaccessible
IS_GATE_SITE = Fl(23), // consider placing a locked door here
IS_IN_ROOM_MACHINE = Fl(24),
IS_IN_AREA_MACHINE = Fl(25),
IS_POWERED = Fl(26), // has been activated by machine power this turn (flag can probably be eliminated if needed)
IMPREGNABLE = Fl(27), // no tunneling allowed!
TERRAIN_COLORS_DANCING = Fl(28), // colors here will sparkle when the game is idle
TELEPATHIC_VISIBLE = Fl(29), // potions of telepathy let you see through other creatures' eyes
WAS_TELEPATHIC_VISIBLE = Fl(30), // potions of telepathy let you see through other creatures' eyes
IS_IN_MACHINE = (IS_IN_ROOM_MACHINE | IS_IN_AREA_MACHINE), // sacred ground; don't generate items here, or teleport randomly to it
PERMANENT_TILE_FLAGS = (DISCOVERED | MAGIC_MAPPED | ITEM_DETECTED | HAS_ITEM | HAS_DORMANT_MONSTER
| HAS_MONSTER | HAS_STAIRS | SEARCHED_FROM_HERE | PRESSURE_PLATE_DEPRESSED
| STABLE_MEMORY | KNOWN_TO_BE_TRAP_FREE | IN_LOOP
| IS_CHOKEPOINT | IS_GATE_SITE | IS_IN_MACHINE | IMPREGNABLE),
ANY_KIND_OF_VISIBLE = (VISIBLE | CLAIRVOYANT_VISIBLE | TELEPATHIC_VISIBLE),
};
#define TURNS_FOR_FULL_REGEN 300
#define STOMACH_SIZE 2150
#define HUNGER_THRESHOLD (STOMACH_SIZE - 1800)
#define WEAK_THRESHOLD 150
#define FAINT_THRESHOLD 50
#define MAX_EXP_LEVEL 20
#define MAX_EXP 100000000L
#define XPXP_NEEDED_FOR_TELEPATHIC_BOND 1400 // XPXP required to enable telepathic awareness with the ally
#define ROOM_MIN_WIDTH 4
#define ROOM_MAX_WIDTH 20
#define ROOM_MIN_HEIGHT 3
#define ROOM_MAX_HEIGHT 7
#define HORIZONTAL_CORRIDOR_MIN_LENGTH 5
#define HORIZONTAL_CORRIDOR_MAX_LENGTH 15
#define VERTICAL_CORRIDOR_MIN_LENGTH 2
#define VERTICAL_CORRIDOR_MAX_LENGTH 9
#define CROSS_ROOM_MIN_WIDTH 3
#define CROSS_ROOM_MAX_WIDTH 12
#define CROSS_ROOM_MIN_HEIGHT 2
#define CROSS_ROOM_MAX_HEIGHT 5
#define MIN_SCALED_ROOM_DIMENSION 2
#define ROOM_TYPE_COUNT 8
#define CORRIDOR_WIDTH 1
#define WAYPOINT_SIGHT_RADIUS 10
#define MAX_WAYPOINT_COUNT 40
#define MAX_ITEMS_IN_MONSTER_ITEMS_HOPPER 100
// Making these larger means cave generation will take more trials; set them too high and the program will hang.
#define CAVE_MIN_WIDTH 50
#define CAVE_MIN_HEIGHT 20
// Keyboard commands:
#define UP_KEY 'k'
#define DOWN_KEY 'j'
#define LEFT_KEY 'h'
#define RIGHT_KEY 'l'
#define UP_ARROW 63232
#define LEFT_ARROW 63234
#define DOWN_ARROW 63233
#define RIGHT_ARROW 63235
#define UPLEFT_KEY 'y'
#define UPRIGHT_KEY 'u'
#define DOWNLEFT_KEY 'b'
#define DOWNRIGHT_KEY 'n'
#define DESCEND_KEY '>'
#define ASCEND_KEY '<'
#define REST_KEY 'z'
#define AUTO_REST_KEY 'Z'
#define SEARCH_KEY 's'
#define INVENTORY_KEY 'i'
#define ACKNOWLEDGE_KEY ' '
#define EQUIP_KEY 'e'
#define UNEQUIP_KEY 'r'
#define APPLY_KEY 'a'
#define THROW_KEY 't'
#define RETHROW_KEY 'T'
#define RELABEL_KEY 'R'
#define TRUE_COLORS_KEY '\\'
#define AGGRO_DISPLAY_KEY ']'
#define DROP_KEY 'd'
#define CALL_KEY 'c'
#define QUIT_KEY 'Q'
#define MESSAGE_ARCHIVE_KEY 'M'
#define BROGUE_HELP_KEY '?'
#define DISCOVERIES_KEY 'D'
#define EXPLORE_KEY 'x'
#define AUTOPLAY_KEY 'A'
#define SEED_KEY '~'
#define EASY_MODE_KEY '&'
#define ESCAPE_KEY '\033'
#define RETURN_KEY '\012'
#define DELETE_KEY '\177'
#define TAB_KEY '\t'
#define SHIFT_TAB_KEY 25 // Cocoa reports shift-tab this way for some reason.
#define PERIOD_KEY '.'
#define VIEW_RECORDING_KEY 'V'
#define LOAD_SAVED_GAME_KEY 'O'
#define SAVE_GAME_KEY 'S'
#define NEW_GAME_KEY 'N'
#define GRAPHICS_KEY 'G'
#define SWITCH_TO_PLAYING_KEY 'P'
#define NUMPAD_0 48
#define NUMPAD_1 49
#define NUMPAD_2 50
#define NUMPAD_3 51
#define NUMPAD_4 52
#define NUMPAD_5 53
#define NUMPAD_6 54
#define NUMPAD_7 55
#define NUMPAD_8 56
#define NUMPAD_9 57
#define PAGE_UP_KEY 63276
#define PAGE_DOWN_KEY 63277
#define PRINTSCREEN_KEY '\054'
#define UNKNOWN_KEY (128+19)
#define min(x, y) (((x) < (y)) ? (x) : (y))
#define max(x, y) (((x) > (y)) ? (x) : (y))
#define clamp(x, low, hi) (min(hi, max(x, low))) // pins x to the [y, z] interval
#define terrainFlags(x, y) (tileCatalog[pmap[x][y].layers[DUNGEON]].flags \
| tileCatalog[pmap[x][y].layers[LIQUID]].flags \
| tileCatalog[pmap[x][y].layers[SURFACE]].flags \
| tileCatalog[pmap[x][y].layers[GAS]].flags)
#define terrainMechFlags(x, y) (tileCatalog[pmap[x][y].layers[DUNGEON]].mechFlags \
| tileCatalog[pmap[x][y].layers[LIQUID]].mechFlags \
| tileCatalog[pmap[x][y].layers[SURFACE]].mechFlags \
| tileCatalog[pmap[x][y].layers[GAS]].mechFlags)
#ifdef BROGUE_ASSERTS
boolean cellHasTerrainFlag(short x, short y, unsigned long flagMask);
#else
#define cellHasTerrainFlag(x, y, flagMask) ((flagMask) & terrainFlags((x), (y)) ? true : false)
#endif
#define cellHasTMFlag(x, y, flagMask) ((flagMask) & terrainMechFlags((x), (y)) ? true : false)
#define cellHasTerrainType(x, y, terrain) ((pmap[x][y].layers[DUNGEON] == (terrain) \
|| pmap[x][y].layers[LIQUID] == (terrain) \
|| pmap[x][y].layers[SURFACE] == (terrain) \
|| pmap[x][y].layers[GAS] == (terrain)) ? true : false)
#define cellHasKnownTerrainFlag(x, y, flagMask) ((flagMask) & pmap[(x)][(y)].rememberedTerrainFlags ? true : false)
#define cellIsPassableOrDoor(x, y) (!cellHasTerrainFlag((x), (y), T_PATHING_BLOCKER) \
|| (cellHasTMFlag((x), (y), (TM_IS_SECRET | TM_PROMOTES_WITH_KEY | TM_CONNECTS_LEVEL)) \
&& cellHasTerrainFlag((x), (y), T_OBSTRUCTS_PASSABILITY)))
#define coordinatesAreInMap(x, y) ((x) >= 0 && (x) < DCOLS && (y) >= 0 && (y) < DROWS)
#define coordinatesAreInWindow(x, y) ((x) >= 0 && (x) < COLS && (y) >= 0 && (y) < ROWS)
#define mapToWindowX(x) ((x) + STAT_BAR_WIDTH + 1)
#define mapToWindowY(y) ((y) + MESSAGE_LINES)
#define windowToMapX(x) ((x) - STAT_BAR_WIDTH - 1)
#define windowToMapY(y) ((y) - MESSAGE_LINES)
#define playerCanDirectlySee(x, y) (pmap[x][y].flags & VISIBLE)
#define playerCanSee(x, y) (pmap[x][y].flags & ANY_KIND_OF_VISIBLE)
#define playerCanSeeOrSense(x, y) ((pmap[x][y].flags & ANY_KIND_OF_VISIBLE) \
|| (rogue.playbackOmniscience \
&& (pmap[x][y].layers[DUNGEON] != GRANITE || (pmap[x][y].flags & DISCOVERED))))
#define CYCLE_MONSTERS_AND_PLAYERS(x) for ((x) = &player; (x) != NULL; (x) = ((x) == &player ? monsters->nextCreature : (x)->nextCreature))
#define assureCosmeticRNG short oldRNG = rogue.RNG; rogue.RNG = RNG_COSMETIC;
#define restoreRNG rogue.RNG = oldRNG;
#define MIN_COLOR_DIFF 600
// weighted sum of the squares of the component differences. Weights are according to color perception.
#define COLOR_DIFF(f, b) (((f).red - (b).red) * ((f).red - (b).red) * 0.2126 \
+ ((f).green - (b).green) * ((f).green - (b).green) * 0.7152 \
+ ((f).blue - (b).blue) * ((f).blue - (b).blue) * 0.0722)
// structs
enum dungeonLayers {
NO_LAYER = -1,
DUNGEON = 0, // dungeon-level tile (e.g. walls)
LIQUID, // liquid-level tile (e.g. lava)
GAS, // gas-level tile (e.g. fire, smoke, swamp gas)
SURFACE, // surface-level tile (e.g. grass)
NUMBER_TERRAIN_LAYERS
};
// keeps track of graphics so we only redraw if the cell has changed:
typedef struct cellDisplayBuffer {
enum displayGlyph character;
char foreColorComponents[3];
char backColorComponents[3];
char opacity;
boolean needsUpdate;
} cellDisplayBuffer;
typedef struct pcell { // permanent cell; have to remember this stuff to save levels
enum tileType layers[NUMBER_TERRAIN_LAYERS]; // terrain
unsigned long flags; // non-terrain cell flags
unsigned short volume; // quantity of gas in cell
unsigned char machineNumber;
cellDisplayBuffer rememberedAppearance; // how the player remembers the cell to look
enum itemCategory rememberedItemCategory; // what category of item the player remembers lying there
short rememberedItemKind; // what kind of item the player remembers lying there
short rememberedItemQuantity; // how many of the item the player remembers lying there
short rememberedItemOriginDepth; // the origin depth of the item the player remembers lying there
enum tileType rememberedTerrain; // what the player remembers as the terrain (i.e. highest priority terrain upon last seeing)
unsigned long rememberedCellFlags; // map cell flags the player remembers from that spot
unsigned long rememberedTerrainFlags; // terrain flags the player remembers from that spot
unsigned long rememberedTMFlags; // TM flags the player remembers from that spot
} pcell;
typedef struct tcell { // transient cell; stuff we don't need to remember between levels
short light[3]; // RGB components of lighting
short oldLight[3]; // compare with subsequent lighting to determine whether to refresh cell
} tcell;
typedef struct randomRange {
short lowerBound;
short upperBound;
short clumpFactor;
} randomRange;
typedef struct color {
// base RGB components:
short red;
short green;
short blue;
// random RGB components to add to base components:
short redRand;
short greenRand;
short blueRand;
// random scalar to add to all components:
short rand;
// Flag: this color "dances" with every refresh:
boolean colorDances;
} color;
enum itemFlags {
ITEM_IDENTIFIED = Fl(0),
ITEM_EQUIPPED = Fl(1),
ITEM_CURSED = Fl(2),
ITEM_PROTECTED = Fl(3),
// unused = Fl(4),
ITEM_RUNIC = Fl(5),
ITEM_RUNIC_HINTED = Fl(6),
ITEM_RUNIC_IDENTIFIED = Fl(7),
ITEM_CAN_BE_IDENTIFIED = Fl(8),
ITEM_PREPLACED = Fl(9),
ITEM_FLAMMABLE = Fl(10),
ITEM_MAGIC_DETECTED = Fl(11),
ITEM_MAX_CHARGES_KNOWN = Fl(12),
ITEM_IS_KEY = Fl(13),
ITEM_ATTACKS_STAGGER = Fl(14), // mace, hammer
ITEM_ATTACKS_EXTEND = Fl(15), // whip
ITEM_ATTACKS_QUICKLY = Fl(16), // rapier
ITEM_ATTACKS_PENETRATE = Fl(17), // spear, pike
ITEM_ATTACKS_ALL_ADJACENT=Fl(18), // axe, war axe
ITEM_LUNGE_ATTACKS = Fl(19), // rapier
ITEM_SNEAK_ATTACK_BONUS = Fl(20), // dagger
ITEM_PASS_ATTACKS = Fl(21), // flail
ITEM_KIND_AUTO_ID = Fl(22), // the item type will become known when the item is picked up.
ITEM_PLAYER_AVOIDS = Fl(23), // explore and travel will try to avoid picking the item up
};
#define KEY_ID_MAXIMUM 20
typedef struct keyLocationProfile {
short x;
short y;
short machine;
boolean disposableHere;
} keyLocationProfile;
typedef struct item {
unsigned short category;
short kind;
unsigned long flags;
randomRange damage;
short armor;
short charges;
short enchant1;
short enchant2;
short timesEnchanted;
enum monsterTypes vorpalEnemy;
short strengthRequired;
unsigned short quiverNumber;
enum displayGlyph displayChar;
color *foreColor;
color *inventoryColor;
short quantity;
char inventoryLetter;
char inscription[DCOLS];
short xLoc;
short yLoc;
keyLocationProfile keyLoc[KEY_ID_MAXIMUM];
short originDepth;
struct item *nextItem;
} item;
typedef struct itemTable {
char *name;
char *flavor;
char callTitle[30];
short frequency;
short marketValue;
short strengthRequired;
randomRange range;
boolean identified;
boolean called;
char description[1500];
} itemTable;
enum dungeonFeatureTypes {
DF_GRANITE_COLUMN = 1,
DF_CRYSTAL_WALL,
DF_LUMINESCENT_FUNGUS,
DF_GRASS,
DF_DEAD_GRASS,
DF_BONES,
DF_RUBBLE,
DF_FOLIAGE,
DF_FUNGUS_FOREST,
DF_DEAD_FOLIAGE,
DF_SUNLIGHT,
DF_DARKNESS,
DF_SHOW_DOOR,
DF_SHOW_POISON_GAS_TRAP,
DF_SHOW_PARALYSIS_GAS_TRAP,
DF_SHOW_TRAPDOOR_HALO,
DF_SHOW_TRAPDOOR,
DF_SHOW_CONFUSION_GAS_TRAP,
DF_SHOW_FLAMETHROWER_TRAP,
DF_SHOW_FLOOD_TRAP,
DF_SHOW_NET_TRAP,
DF_SHOW_ALARM_TRAP,
DF_RED_BLOOD,
DF_GREEN_BLOOD,
DF_PURPLE_BLOOD,
DF_WORM_BLOOD,
DF_ACID_BLOOD,
DF_ASH_BLOOD,
DF_EMBER_BLOOD,
DF_ECTOPLASM_BLOOD,
DF_RUBBLE_BLOOD,
DF_ROT_GAS_BLOOD,
DF_VOMIT,
DF_BLOAT_DEATH,
DF_BLOAT_EXPLOSION,
DF_BLOOD_EXPLOSION,
DF_FLAMEDANCER_CORONA,
DF_MUTATION_EXPLOSION,
DF_MUTATION_LICHEN,
DF_REPEL_CREATURES,
DF_ROT_GAS_PUFF,
DF_STEAM_PUFF,
DF_STEAM_ACCUMULATION,
DF_METHANE_GAS_PUFF,
DF_SALAMANDER_FLAME,
DF_URINE,
DF_UNICORN_POOP,
DF_PUDDLE,
DF_ASH,
DF_ECTOPLASM_DROPLET,
DF_FORCEFIELD,
DF_FORCEFIELD_MELT,
DF_SACRED_GLYPHS,
DF_LICHEN_GROW,
DF_TUNNELIZE,
DF_SHATTERING_SPELL,
// spiderwebs
DF_WEB_SMALL,
DF_WEB_LARGE,
// ancient spirit
DF_ANCIENT_SPIRIT_VINES,
DF_ANCIENT_SPIRIT_GRASS,
// foliage
DF_TRAMPLED_FOLIAGE,
DF_SMALL_DEAD_GRASS,
DF_FOLIAGE_REGROW,
DF_TRAMPLED_FUNGUS_FOREST,
DF_FUNGUS_FOREST_REGROW,
// brimstone
DF_ACTIVE_BRIMSTONE,
DF_INERT_BRIMSTONE,
// bloodwort
DF_BLOODFLOWER_PODS_GROW_INITIAL,
DF_BLOODFLOWER_PODS_GROW,
DF_BLOODFLOWER_POD_BURST,
// dewars
DF_DEWAR_CAUSTIC,
DF_DEWAR_CONFUSION,
DF_DEWAR_PARALYSIS,
DF_DEWAR_METHANE,
DF_DEWAR_GLASS,
DF_CARPET_AREA,
// algae
DF_BUILD_ALGAE_WELL,
DF_ALGAE_1,
DF_ALGAE_2,
DF_ALGAE_REVERT,
DF_OPEN_DOOR,
DF_CLOSED_DOOR,
DF_OPEN_IRON_DOOR_INERT,
DF_ITEM_CAGE_OPEN,
DF_ITEM_CAGE_CLOSE,
DF_ALTAR_INERT,
DF_ALTAR_RETRACT,
DF_PORTAL_ACTIVATE,
DF_INACTIVE_GLYPH,
DF_ACTIVE_GLYPH,
DF_SILENT_GLYPH_GLOW,
DF_GUARDIAN_STEP,
DF_MIRROR_TOTEM_STEP,
DF_GLYPH_CIRCLE,
DF_REVEAL_LEVER,
DF_PULL_LEVER,
DF_CREATE_LEVER,
DF_BRIDGE_FALL_PREP,
DF_BRIDGE_FALL,
DF_PLAIN_FIRE,
DF_GAS_FIRE,
DF_EXPLOSION_FIRE,
DF_DART_EXPLOSION,
DF_BRIMSTONE_FIRE,
DF_BRIDGE_FIRE,
DF_FLAMETHROWER,
DF_EMBERS,
DF_EMBERS_PATCH,
DF_OBSIDIAN,
DF_ITEM_FIRE,
DF_CREATURE_FIRE,
DF_FLOOD,
DF_FLOOD_2,
DF_FLOOD_DRAIN,
DF_HOLE_2,
DF_HOLE_DRAIN,
DF_DEEP_WATER_FREEZE,
DF_ALGAE_1_FREEZE,
DF_ALGAE_2_FREEZE,
DF_DEEP_WATER_MELTING,
DF_DEEP_WATER_THAW,
DF_SHALLOW_WATER_FREEZE,
DF_SHALLOW_WATER_MELTING,
DF_SHALLOW_WATER_THAW,
DF_POISON_GAS_CLOUD,
DF_CONFUSION_GAS_TRAP_CLOUD,
DF_NET,
DF_AGGRAVATE_TRAP,
DF_METHANE_GAS_ARMAGEDDON,
// potions
DF_POISON_GAS_CLOUD_POTION,
DF_PARALYSIS_GAS_CLOUD_POTION,
DF_CONFUSION_GAS_CLOUD_POTION,
DF_INCINERATION_POTION,
DF_DARKNESS_POTION,
DF_HOLE_POTION,
DF_LICHEN_PLANTED,
// other items
DF_ARMOR_IMMOLATION,
DF_STAFF_HOLE,
DF_STAFF_HOLE_EDGE,
// commutation altar
DF_ALTAR_COMMUTE,
DF_MAGIC_PIPING,
DF_INERT_PIPE,
// resurrection altar
DF_ALTAR_RESURRECT,
DF_MACHINE_FLOOR_TRIGGER_REPEATING,
// sacrifice altar
DF_SACRIFICE_ALTAR,
DF_SACRIFICE_COMPLETE,
DF_SACRIFICE_CAGE_ACTIVE,
// vampire in coffin
DF_COFFIN_BURSTS,
DF_COFFIN_BURNS,
DF_TRIGGER_AREA,
// throwing tutorial -- button in chasm
DF_CAGE_DISAPPEARS,
DF_MEDIUM_HOLE,
DF_MEDIUM_LAVA_POND,
DF_MACHINE_PRESSURE_PLATE_USED,
// rat trap
DF_WALL_CRACK,
// wooden barricade at entrance
DF_WOODEN_BARRICADE_BURN,
// wooden barricade around altar, dead grass all around
DF_SURROUND_WOODEN_BARRICADE,
// pools of water that, when triggered, slowly expand to fill the room
DF_SPREADABLE_WATER,
DF_SHALLOW_WATER,
DF_WATER_SPREADS,
DF_SPREADABLE_WATER_POOL,
DF_SPREADABLE_DEEP_WATER_POOL,
// when triggered, the ground gradually turns into chasm:
DF_SPREADABLE_COLLAPSE,
DF_COLLAPSE,
DF_COLLAPSE_SPREADS,
DF_ADD_MACHINE_COLLAPSE_EDGE_DORMANT,
// when triggered, a bridge appears:
DF_BRIDGE_ACTIVATE,
DF_BRIDGE_ACTIVATE_ANNOUNCE,
DF_BRIDGE_APPEARS,
DF_ADD_DORMANT_CHASM_HALO,
// when triggered, the lava retracts:
DF_LAVA_RETRACTABLE,
DF_RETRACTING_LAVA,
DF_OBSIDIAN_WITH_STEAM,
// when triggered, the door seals and caustic gas fills the room
DF_SHOW_POISON_GAS_VENT,
DF_POISON_GAS_VENT_OPEN,
DF_ACTIVATE_PORTCULLIS,
DF_OPEN_PORTCULLIS,
DF_VENT_SPEW_POISON_GAS,
// when triggered, pilot light ignites and explosive gas fills the room
DF_SHOW_METHANE_VENT,
DF_METHANE_VENT_OPEN,
DF_VENT_SPEW_METHANE,
DF_PILOT_LIGHT,
// paralysis trap: trigger plate with gas vents nearby
DF_DISCOVER_PARALYSIS_VENT,
DF_PARALYSIS_VENT_SPEW,
DF_REVEAL_PARALYSIS_VENT_SILENTLY,
// thematic dungeon
DF_AMBIENT_BLOOD,
// statues crack for a few turns and then shatter, revealing the monster inside
DF_CRACKING_STATUE,
DF_STATUE_SHATTER,
// a turret appears:
DF_TURRET_EMERGE,
// an elaborate worm catacomb opens up
DF_WORM_TUNNEL_MARKER_DORMANT,
DF_WORM_TUNNEL_MARKER_ACTIVE,
DF_GRANITE_CRUMBLES,
DF_WALL_OPEN,
// the room gradually darkens
DF_DARKENING_FLOOR,
DF_DARK_FLOOR,
DF_HAUNTED_TORCH_TRANSITION,
DF_HAUNTED_TORCH,
// bubbles rise from the mud and bog monsters spawn
DF_MUD_DORMANT,
DF_MUD_ACTIVATE,
// crystals charge when hit by lightning
DF_ELECTRIC_CRYSTAL_ON,
DF_TURRET_LEVER,
// idyll:
DF_SHALLOW_WATER_POOL,
DF_DEEP_WATER_POOL,
// swamp:
DF_SWAMP_WATER,
DF_SWAMP,
DF_SWAMP_MUD,
// camp:
DF_HAY,
DF_JUNK,
// remnants:
DF_REMNANT,
DF_REMNANT_ASH,
// chasm catwalk:
DF_CHASM_HOLE,
DF_CATWALK_BRIDGE,
// lake catwalk:
DF_LAKE_CELL,
DF_LAKE_HALO,
// worm den:
DF_WALL_SHATTER,
// monster cages open:
DF_MONSTER_CAGE_OPENS,
// goblin warren:
DF_STENCH_BURN,
DF_STENCH_SMOLDER,
NUMBER_DUNGEON_FEATURES,
};
enum dungeonProfileTypes {
DP_BASIC,
DP_BASIC_FIRST_ROOM,
DP_GOBLIN_WARREN,
DP_SENTINEL_SANCTUARY,
NUMBER_DUNGEON_PROFILES,
};
typedef struct lightSource {
const color *lightColor;
randomRange lightRadius;
short radialFadeToPercent;
boolean passThroughCreatures; // generally no, but miner light does
} lightSource;
typedef struct flare {
lightSource *light; // Flare light
short coeffChangeAmount; // The constant amount by which the coefficient changes per frame, e.g. -25 means it gets 25% dimmer per frame.
short coeffLimit; // Flare ends if the coefficient passes this percentage (whether going up or down).
short xLoc, yLoc; // Current flare location.
long coeff; // Current flare coefficient; always starts at 100.
unsigned long turnNumber; // So we can eliminate those that fired one or more turns ago.
} flare;
enum DFFlags {
DFF_EVACUATE_CREATURES_FIRST = Fl(0), // Creatures in the DF area get moved outside of it
DFF_SUBSEQ_EVERYWHERE = Fl(1), // Subsequent DF spawns in every cell that this DF spawns in, instead of only the origin
DFF_TREAT_AS_BLOCKING = Fl(2), // If filling the footprint of this DF with walls would disrupt level connectivity, then abort.
DFF_PERMIT_BLOCKING = Fl(3), // Generate this DF without regard to level connectivity.
DFF_ACTIVATE_DORMANT_MONSTER = Fl(4), // Dormant monsters on this tile will appear -- e.g. when a statue bursts to reveal a monster.
DFF_CLEAR_OTHER_TERRAIN = Fl(5), // Erase other terrain in the footprint of this DF.
DFF_BLOCKED_BY_OTHER_LAYERS = Fl(6), // Will not propagate into a cell if any layer in that cell has a superior priority.
DFF_SUPERPRIORITY = Fl(7), // Will overwrite terrain of a superior priority.
DFF_AGGRAVATES_MONSTERS = Fl(8), // Will act as though an aggravate monster scroll of effectRadius radius had been read at that point.
DFF_RESURRECT_ALLY = Fl(9), // Will bring back to life your most recently deceased ally.
};
enum boltEffects {
BE_NONE,
BE_ATTACK,
BE_TELEPORT,
BE_SLOW,
BE_POLYMORPH,
BE_NEGATION,
BE_DOMINATION,
BE_BECKONING,
BE_PLENTY,
BE_INVISIBILITY,
BE_EMPOWERMENT,
BE_DAMAGE,
BE_POISON,
BE_TUNNELING,
BE_BLINKING,
BE_ENTRANCEMENT,
BE_OBSTRUCTION,
BE_DISCORD,
BE_CONJURATION,
BE_HEALING,
BE_HASTE,
BE_SHIELDING,
};
enum boltFlags {
BF_PASSES_THRU_CREATURES = Fl(0), // Bolt continues through creatures (e.g. lightning and tunneling)
BF_HALTS_BEFORE_OBSTRUCTION = Fl(1), // Bolt takes effect the space before it terminates (e.g. conjuration, obstruction, blinking)
BF_TARGET_ALLIES = Fl(2), // Staffs/wands/creatures that shoot this bolt will auto-target allies.
BF_TARGET_ENEMIES = Fl(3), // Staffs/wands/creatures that shoot this bolt will auto-target enemies.
BF_FIERY = Fl(4), // Bolt will light flammable terrain on fire as it passes, and will ignite monsters hit.
BF_NEVER_REFLECTS = Fl(6), // Bolt will never reflect (e.g. spiderweb, arrows).
BF_NOT_LEARNABLE = Fl(7), // This technique cannot be absorbed by empowered allies.
BF_NOT_NEGATABLE = Fl(8), // Won't be erased by negation.
BF_ELECTRIC = Fl(9), // Activates terrain that has TM_PROMOTES_ON_ELECTRICITY
BF_DISPLAY_CHAR_ALONG_LENGTH = Fl(10), // Display the character along the entire length of the bolt instead of just at the front.
};
typedef struct bolt {
char name[DCOLS];
char description[COLS];
char abilityDescription[COLS*2];
enum displayGlyph theChar;
const color *foreColor;
const color *backColor;
short boltEffect;
short magnitude;
short pathDF;
short targetDF;
unsigned long forbiddenMonsterFlags;
unsigned long flags;
} bolt;
// Level profiles, affecting what rooms get chosen and how they're connected:
typedef struct dungeonProfile {
// Room type weights (in the natural dungeon, these are also adjusted based on depth):
short roomFrequencies[ROOM_TYPE_COUNT];
short corridorChance;
} dungeonProfile;
// Dungeon features, spawned from Architect.c:
typedef struct dungeonFeature {
// tile info:
enum tileType tile;
enum dungeonLayers layer;
// spawning pattern:
short startProbability;
short probabilityDecrement;
unsigned long flags;
char description[DCOLS];
enum lightType lightFlare;
const color *flashColor;
short effectRadius;
enum tileType propagationTerrain;
enum dungeonFeatureTypes subsequentDF;
boolean messageDisplayed;
} dungeonFeature;
// Terrain types:
typedef struct floorTileType {
// appearance:
enum displayGlyph displayChar;
const color *foreColor;
const color *backColor;
short drawPriority; // priority (lower number means higher priority); governs drawing as well as tile replacement comparisons.
char chanceToIgnite; // chance to burn if a flame terrain is on one of the four cardinal neighbors
enum dungeonFeatureTypes fireType; // spawn this DF when the terrain ignites (or, if it's T_IS_DF_TRAP, when the pressure plate clicks)
enum dungeonFeatureTypes discoverType; // spawn this DF when successfully searched if T_IS_SECRET is set
enum dungeonFeatureTypes promoteType; // creates this dungeon spawn type when it promotes for some other reason (random promotion or promotion through machine activation)
short promoteChance; // percent chance per turn to spawn the promotion type; will also vanish upon doing so if T_VANISHES_UPON_PROMOTION is set
short glowLight; // if it glows, this is the ID of the light type
unsigned long flags;
unsigned long mechFlags;
char description[COLS];
char flavorText[COLS];
} floorTileType;
enum terrainFlagCatalog {
T_OBSTRUCTS_PASSABILITY = Fl(0), // cannot be walked through
T_OBSTRUCTS_VISION = Fl(1), // blocks line of sight
T_OBSTRUCTS_ITEMS = Fl(2), // items can't be on this tile
T_OBSTRUCTS_SURFACE_EFFECTS = Fl(3), // grass, blood, etc. cannot exist on this tile
T_OBSTRUCTS_GAS = Fl(4), // blocks the permeation of gas
T_OBSTRUCTS_DIAGONAL_MOVEMENT = Fl(5), // can't step diagonally around this tile
T_SPONTANEOUSLY_IGNITES = Fl(6), // monsters avoid unless chasing player or immune to fire
T_AUTO_DESCENT = Fl(7), // automatically drops creatures down a depth level and does some damage (2d6)
T_LAVA_INSTA_DEATH = Fl(8), // kills any non-levitating non-fire-immune creature instantly
T_CAUSES_POISON = Fl(9), // any non-levitating creature gets 10 poison
T_IS_FLAMMABLE = Fl(10), // terrain can catch fire
T_IS_FIRE = Fl(11), // terrain is a type of fire; ignites neighboring flammable cells
T_ENTANGLES = Fl(12), // entangles players and monsters like a spiderweb
T_IS_DEEP_WATER = Fl(13), // steals items 50% of the time and moves them around randomly
T_CAUSES_DAMAGE = Fl(14), // anything on the tile takes max(1-2, 10%) damage per turn
T_CAUSES_NAUSEA = Fl(15), // any creature on the tile becomes nauseous
T_CAUSES_PARALYSIS = Fl(16), // anything caught on this tile is paralyzed
T_CAUSES_CONFUSION = Fl(17), // causes creatures on this tile to become confused
T_CAUSES_HEALING = Fl(18), // heals 20% max HP per turn for any player or non-inanimate monsters
T_IS_DF_TRAP = Fl(19), // spews gas of type specified in fireType when stepped on
T_CAUSES_EXPLOSIVE_DAMAGE = Fl(20), // is an explosion; deals higher of 15-20 or 50% damage instantly, but not again for five turns
T_SACRED = Fl(21), // monsters that aren't allies of the player will avoid stepping here
T_OBSTRUCTS_SCENT = (T_OBSTRUCTS_PASSABILITY | T_OBSTRUCTS_VISION | T_AUTO_DESCENT | T_LAVA_INSTA_DEATH | T_IS_DEEP_WATER | T_SPONTANEOUSLY_IGNITES),
T_PATHING_BLOCKER = (T_OBSTRUCTS_PASSABILITY | T_AUTO_DESCENT | T_IS_DF_TRAP | T_LAVA_INSTA_DEATH | T_IS_DEEP_WATER | T_IS_FIRE | T_SPONTANEOUSLY_IGNITES),
T_DIVIDES_LEVEL = (T_OBSTRUCTS_PASSABILITY | T_AUTO_DESCENT | T_IS_DF_TRAP | T_LAVA_INSTA_DEATH | T_IS_DEEP_WATER),
T_LAKE_PATHING_BLOCKER = (T_AUTO_DESCENT | T_LAVA_INSTA_DEATH | T_IS_DEEP_WATER | T_SPONTANEOUSLY_IGNITES),
T_WAYPOINT_BLOCKER = (T_OBSTRUCTS_PASSABILITY | T_AUTO_DESCENT | T_IS_DF_TRAP | T_LAVA_INSTA_DEATH | T_IS_DEEP_WATER | T_SPONTANEOUSLY_IGNITES),
T_MOVES_ITEMS = (T_IS_DEEP_WATER | T_LAVA_INSTA_DEATH),
T_CAN_BE_BRIDGED = (T_AUTO_DESCENT),
T_OBSTRUCTS_EVERYTHING = (T_OBSTRUCTS_PASSABILITY | T_OBSTRUCTS_VISION | T_OBSTRUCTS_ITEMS | T_OBSTRUCTS_GAS | T_OBSTRUCTS_SURFACE_EFFECTS | T_OBSTRUCTS_DIAGONAL_MOVEMENT),
T_HARMFUL_TERRAIN = (T_CAUSES_POISON | T_IS_FIRE | T_CAUSES_DAMAGE | T_CAUSES_PARALYSIS | T_CAUSES_CONFUSION | T_CAUSES_EXPLOSIVE_DAMAGE),
T_RESPIRATION_IMMUNITIES = (T_CAUSES_DAMAGE | T_CAUSES_CONFUSION | T_CAUSES_PARALYSIS | T_CAUSES_NAUSEA),
};
enum terrainMechanicalFlagCatalog {
TM_IS_SECRET = Fl(0), // successful search or being stepped on while visible transforms it into discoverType
TM_PROMOTES_WITH_KEY = Fl(1), // promotes if the key is present on the tile (in your pack, carried by monster, or lying on the ground)
TM_PROMOTES_WITHOUT_KEY = Fl(2), // promotes if the key is NOT present on the tile (in your pack, carried by monster, or lying on the ground)
TM_PROMOTES_ON_STEP = Fl(3), // promotes when a creature, player or item is on the tile (whether or not levitating)
TM_PROMOTES_ON_ITEM_PICKUP = Fl(4), // promotes when an item is lifted from the tile (primarily for altars)
TM_PROMOTES_ON_PLAYER_ENTRY = Fl(5), // promotes when the player enters the tile (whether or not levitating)
TM_PROMOTES_ON_SACRIFICE_ENTRY = Fl(6), // promotes when the sacrifice target enters the tile (whether or not levitating)
TM_PROMOTES_ON_ELECTRICITY = Fl(7), // promotes when hit by a lightning bolt
TM_ALLOWS_SUBMERGING = Fl(8), // allows submersible monsters to submerge in this terrain
TM_IS_WIRED = Fl(9), // if wired, promotes when powered, and sends power when promoting
TM_IS_CIRCUIT_BREAKER = Fl(10), // prevents power from circulating in its machine
TM_GAS_DISSIPATES = Fl(11), // does not just hang in the air forever
TM_GAS_DISSIPATES_QUICKLY = Fl(12), // dissipates quickly
TM_EXTINGUISHES_FIRE = Fl(13), // extinguishes burning terrain or creatures
TM_VANISHES_UPON_PROMOTION = Fl(14), // vanishes when creating promotion dungeon feature, even if the replacement terrain priority doesn't require it
TM_REFLECTS_BOLTS = Fl(15), // magic bolts reflect off of its surface randomly (similar to pmap flag IMPREGNABLE)
TM_STAND_IN_TILE = Fl(16), // earthbound creatures will be said to stand "in" the tile, not on it
TM_LIST_IN_SIDEBAR = Fl(17), // terrain will be listed in the sidebar with a description of the terrain type
TM_VISUALLY_DISTINCT = Fl(18), // terrain will be color-adjusted if necessary so the character stands out from the background
TM_BRIGHT_MEMORY = Fl(19), // no blue fade when this tile is out of sight
TM_EXPLOSIVE_PROMOTE = Fl(20), // when burned, will promote to promoteType instead of burningType if surrounded by tiles with T_IS_FIRE or TM_EXPLOSIVE_PROMOTE
TM_CONNECTS_LEVEL = Fl(21), // will be treated as passable for purposes of calculating level connectedness, irrespective of other aspects of this terrain layer
TM_INTERRUPT_EXPLORATION_WHEN_SEEN = Fl(22), // will generate a message when discovered during exploration to interrupt exploration
TM_INVERT_WHEN_HIGHLIGHTED = Fl(23), // will flip fore and back colors when highlighted with pathing
TM_SWAP_ENCHANTS_ACTIVATION = Fl(24), // in machine, swap item enchantments when two suitable items are on this terrain, and activate the machine when that happens
};
enum statusEffects {
STATUS_SEARCHING = 0,
STATUS_DONNING,
STATUS_WEAKENED,
STATUS_TELEPATHIC,
STATUS_HALLUCINATING,
STATUS_LEVITATING,
STATUS_SLOWED,
STATUS_HASTED,
STATUS_CONFUSED,
STATUS_BURNING,
STATUS_PARALYZED,
STATUS_POISONED,
STATUS_STUCK,
STATUS_NAUSEOUS,
STATUS_DISCORDANT,
STATUS_IMMUNE_TO_FIRE,
STATUS_EXPLOSION_IMMUNITY,
STATUS_NUTRITION,
STATUS_ENTERS_LEVEL_IN,
STATUS_MAGICAL_FEAR,
STATUS_ENTRANCED,
STATUS_DARKNESS,
STATUS_LIFESPAN_REMAINING,
STATUS_SHIELDED,
STATUS_INVISIBLE,
STATUS_AGGRAVATING,
NUMBER_OF_STATUS_EFFECTS,
};
enum hordeFlags {
HORDE_DIES_ON_LEADER_DEATH = Fl(0), // if the leader dies, the horde will die instead of electing new leader
HORDE_IS_SUMMONED = Fl(1), // minions summoned when any creature is the same species as the leader and casts summon
HORDE_SUMMONED_AT_DISTANCE = Fl(2), // summons will appear across the level, and will naturally path back to the leader
HORDE_LEADER_CAPTIVE = Fl(3), // the leader is in chains and the followers are guards
HORDE_NO_PERIODIC_SPAWN = Fl(4), // can spawn only when the level begins -- not afterwards
HORDE_ALLIED_WITH_PLAYER = Fl(5),
HORDE_MACHINE_BOSS = Fl(6), // used in machines for a boss challenge
HORDE_MACHINE_WATER_MONSTER = Fl(7), // used in machines where the room floods with shallow water
HORDE_MACHINE_CAPTIVE = Fl(8), // powerful captive monsters without any captors
HORDE_MACHINE_STATUE = Fl(9), // the kinds of monsters that make sense in a statue
HORDE_MACHINE_TURRET = Fl(10), // turrets, for hiding in walls
HORDE_MACHINE_MUD = Fl(11), // bog monsters, for hiding in mud
HORDE_MACHINE_KENNEL = Fl(12), // monsters that can appear in cages in kennels
HORDE_VAMPIRE_FODDER = Fl(13), // monsters that are prone to capture and farming by vampires
HORDE_MACHINE_LEGENDARY_ALLY = Fl(14), // legendary allies
HORDE_NEVER_OOD = Fl(15), // Horde cannot be generated out of depth
HORDE_MACHINE_THIEF = Fl(16), // monsters that can be generated in the key thief area machines
HORDE_MACHINE_GOBLIN_WARREN = Fl(17), // can spawn in goblin warrens
HORDE_SACRIFICE_TARGET = Fl(18), // can be the target of an assassination challenge; leader will get scary light.
HORDE_MACHINE_ONLY = (HORDE_MACHINE_BOSS | HORDE_MACHINE_WATER_MONSTER
| HORDE_MACHINE_CAPTIVE | HORDE_MACHINE_STATUE
| HORDE_MACHINE_TURRET | HORDE_MACHINE_MUD
| HORDE_MACHINE_KENNEL | HORDE_VAMPIRE_FODDER
| HORDE_MACHINE_LEGENDARY_ALLY | HORDE_MACHINE_THIEF
| HORDE_MACHINE_GOBLIN_WARREN
| HORDE_SACRIFICE_TARGET),
};
enum monsterBehaviorFlags {
MONST_INVISIBLE = Fl(0), // monster is invisible
MONST_INANIMATE = Fl(1), // monster has abbreviated stat bar display and is immune to many things
MONST_IMMOBILE = Fl(2), // monster won't move or perform melee attacks
MONST_CARRY_ITEM_100 = Fl(3), // monster carries an item 100% of the time
MONST_CARRY_ITEM_25 = Fl(4), // monster carries an item 25% of the time
MONST_ALWAYS_HUNTING = Fl(5), // monster is never asleep or in wandering mode
MONST_FLEES_NEAR_DEATH = Fl(6), // monster flees when under 25% health and re-engages when over 75%
MONST_ATTACKABLE_THRU_WALLS = Fl(7), // can be attacked when embedded in a wall
MONST_DEFEND_DEGRADE_WEAPON = Fl(8), // hitting the monster damages the weapon
MONST_IMMUNE_TO_WEAPONS = Fl(9), // weapons ineffective
MONST_FLIES = Fl(10), // permanent levitation
MONST_FLITS = Fl(11), // moves randomly a third of the time
MONST_IMMUNE_TO_FIRE = Fl(12), // won't burn, won't die in lava
MONST_CAST_SPELLS_SLOWLY = Fl(13), // takes twice the attack duration to cast a spell
MONST_IMMUNE_TO_WEBS = Fl(14), // monster passes freely through webs
MONST_REFLECT_4 = Fl(15), // monster reflects projectiles as though wearing +4 armor of reflection
MONST_NEVER_SLEEPS = Fl(16), // monster is always awake
MONST_FIERY = Fl(17), // monster carries an aura of flame (but no automatic fire light)
MONST_INVULNERABLE = Fl(18), // monster is immune to absolutely everything
MONST_IMMUNE_TO_WATER = Fl(19), // monster moves at full speed in deep water and (if player) doesn't drop items
MONST_RESTRICTED_TO_LIQUID = Fl(20), // monster can move only on tiles that allow submersion
MONST_SUBMERGES = Fl(21), // monster can submerge in appropriate terrain
MONST_MAINTAINS_DISTANCE = Fl(22), // monster tries to keep a distance of 3 tiles between it and player
MONST_WILL_NOT_USE_STAIRS = Fl(23), // monster won't chase the player between levels
MONST_DIES_IF_NEGATED = Fl(24), // monster will die if exposed to negation magic
MONST_MALE = Fl(25), // monster is male (or 50% likely to be male if also has MONST_FEMALE)
MONST_FEMALE = Fl(26), // monster is female (or 50% likely to be female if also has MONST_MALE)
MONST_NOT_LISTED_IN_SIDEBAR = Fl(27), // monster doesn't show up in the sidebar
MONST_GETS_TURN_ON_ACTIVATION = Fl(28), // monster never gets a turn, except when its machine is activated
MONST_ALWAYS_USE_ABILITY = Fl(29), // monster will never fail to use special ability if eligible (no random factor)
MONST_NO_POLYMORPH = Fl(30), // monster cannot result from a polymorph spell (liches, phoenixes and Warden of Yendor)
NEGATABLE_TRAITS = (MONST_INVISIBLE | MONST_DEFEND_DEGRADE_WEAPON | MONST_IMMUNE_TO_WEAPONS | MONST_FLIES
| MONST_FLITS | MONST_IMMUNE_TO_FIRE | MONST_REFLECT_4 | MONST_FIERY | MONST_MAINTAINS_DISTANCE),
MONST_TURRET = (MONST_IMMUNE_TO_WEBS | MONST_NEVER_SLEEPS | MONST_IMMOBILE | MONST_INANIMATE |
MONST_ATTACKABLE_THRU_WALLS | MONST_WILL_NOT_USE_STAIRS),
LEARNABLE_BEHAVIORS = (MONST_INVISIBLE | MONST_FLIES | MONST_IMMUNE_TO_FIRE | MONST_REFLECT_4),
MONST_NEVER_VORPAL_ENEMY = (MONST_INANIMATE | MONST_INVULNERABLE | MONST_IMMOBILE | MONST_RESTRICTED_TO_LIQUID | MONST_GETS_TURN_ON_ACTIVATION | MONST_MAINTAINS_DISTANCE),
MONST_NEVER_MUTATED = (MONST_INVISIBLE | MONST_INANIMATE | MONST_IMMOBILE | MONST_INVULNERABLE),
};
enum monsterAbilityFlags {
MA_HIT_HALLUCINATE = Fl(0), // monster can hit to cause hallucinations
MA_HIT_STEAL_FLEE = Fl(1), // monster can steal an item and then run away
MA_HIT_BURN = Fl(2), // monster can hit to set you on fire
MA_ENTER_SUMMONS = Fl(3), // monster will "become" its summoned leader, reappearing when that leader is defeated
MA_HIT_DEGRADE_ARMOR = Fl(4), // monster damages armor
MA_CAST_SUMMON = Fl(5), // requires that there be one or more summon hordes with this monster type as the leader
MA_SEIZES = Fl(6), // monster seizes enemies before attacking
MA_POISONS = Fl(7), // monster's damage is dealt in the form of poison
MA_DF_ON_DEATH = Fl(8), // monster spawns its DF when it dies
MA_CLONE_SELF_ON_DEFEND = Fl(9), // monster splits in two when struck
MA_KAMIKAZE = Fl(10), // monster dies instead of attacking
MA_TRANSFERENCE = Fl(11), // monster recovers 40 or 90% of the damage that it inflicts as health
MA_CAUSES_WEAKNESS = Fl(12), // monster attacks cause weakness status in target
MA_ATTACKS_PENETRATE = Fl(13), // monster attacks all adjacent enemies, like an axe
MA_ATTACKS_ALL_ADJACENT = Fl(14), // monster attacks penetrate one layer of enemies, like a spear
MA_ATTACKS_EXTEND = Fl(15), // monster attacks from a distance in a cardinal direction, like a whip
MA_ATTACKS_STAGGER = Fl(16), // monster attacks will push the player backward by one space if there is room
MA_AVOID_CORRIDORS = Fl(17), // monster will avoid corridors when hunting
SPECIAL_HIT = (MA_HIT_HALLUCINATE | MA_HIT_STEAL_FLEE | MA_HIT_DEGRADE_ARMOR | MA_POISONS
| MA_TRANSFERENCE | MA_CAUSES_WEAKNESS | MA_HIT_BURN | MA_ATTACKS_STAGGER),
LEARNABLE_ABILITIES = (MA_TRANSFERENCE | MA_CAUSES_WEAKNESS),
MA_NON_NEGATABLE_ABILITIES = (MA_ATTACKS_PENETRATE | MA_ATTACKS_ALL_ADJACENT | MA_ATTACKS_EXTEND | MA_ATTACKS_STAGGER),
MA_NEVER_VORPAL_ENEMY = (MA_KAMIKAZE),
MA_NEVER_MUTATED = (MA_KAMIKAZE),
};
enum monsterBookkeepingFlags {
MB_WAS_VISIBLE = Fl(0), // monster was visible to player last turn
MB_TELEPATHICALLY_REVEALED = Fl(1), // player can magically see monster and adjacent cells
MB_PREPLACED = Fl(2), // monster dropped onto the level and requires post-processing
MB_APPROACHING_UPSTAIRS = Fl(3), // following the player up the stairs
MB_APPROACHING_DOWNSTAIRS = Fl(4), // following the player down the stairs
MB_APPROACHING_PIT = Fl(5), // following the player down a pit
MB_LEADER = Fl(6), // monster is the leader of a horde
MB_FOLLOWER = Fl(7), // monster is a member of a horde
MB_CAPTIVE = Fl(8), // monster is all tied up
MB_SEIZED = Fl(9), // monster is being held
MB_SEIZING = Fl(10), // monster is holding another creature immobile
MB_SUBMERGED = Fl(11), // monster is currently submerged and hence invisible until it attacks
MB_JUST_SUMMONED = Fl(12), // used to mark summons so they can be post-processed
MB_WILL_FLASH = Fl(13), // this monster will flash as soon as control is returned to the player
MB_BOUND_TO_LEADER = Fl(14), // monster will die if the leader dies or becomes separated from the leader
MB_MARKED_FOR_SACRIFICE = Fl(15), // scary glow, monster can be sacrificed in the appropriate machine
MB_ABSORBING = Fl(16), // currently learning a skill by absorbing an enemy corpse
MB_DOES_NOT_TRACK_LEADER = Fl(17), // monster will not follow its leader around
MB_IS_FALLING = Fl(18), // monster is plunging downward at the end of the turn
MB_IS_DYING = Fl(19), // monster has already been killed and is awaiting the end-of-turn graveyard sweep (or in purgatory)
MB_GIVEN_UP_ON_SCENT = Fl(20), // to help the monster remember that the scent map is a dead end
MB_IS_DORMANT = Fl(21), // lurking, waiting to burst out
MB_HAS_SOUL = Fl(22), // slaying the monster will count toward weapon auto-ID
MB_ALREADY_SEEN = Fl(23), // seeing this monster won't interrupt exploration
MB_HAS_ENTRANCED_MOVED = Fl(24) // has already moved while entranced and should not move again
};
// Defines all creatures, which include monsters and the player:
typedef struct creatureType {
enum monsterTypes monsterID; // index number for the monsterCatalog
char monsterName[COLS];
enum displayGlyph displayChar;
const color *foreColor;
short maxHP;
short defense;
short accuracy;
randomRange damage;
long turnsBetweenRegen; // turns to wait before regaining 1 HP
short movementSpeed;
short attackSpeed;
enum dungeonFeatureTypes bloodType;
enum lightType intrinsicLightType;
boolean isLarge; // used for size of psychic emanation
short DFChance; // percent chance to spawn the dungeon feature per awake turn
enum dungeonFeatureTypes DFType; // kind of dungeon feature
enum boltType bolts[20];
unsigned long flags;
unsigned long abilityFlags;
} creatureType;
typedef struct monsterWords {
char flavorText[COLS*5];
char absorbing[40];
char absorbStatus[40];
char attack[5][30];
char DFMessage[DCOLS * 2];
char summonMessage[DCOLS * 2];
} monsterWords;
enum creatureStates {
MONSTER_SLEEPING,
MONSTER_TRACKING_SCENT,
MONSTER_WANDERING,
MONSTER_FLEEING,
MONSTER_ALLY,
};
enum creatureModes {
MODE_NORMAL,
MODE_PERM_FLEEING
};
typedef struct mutation {
char title[100];
const color *textColor;
short healthFactor;
short moveSpeedFactor;
short attackSpeedFactor;
short defenseFactor;
short damageFactor;
short DFChance;
enum dungeonFeatureTypes DFType;
enum lightType light;
unsigned long monsterFlags;
unsigned long monsterAbilityFlags;
unsigned long forbiddenFlags;
unsigned long forbiddenAbilityFlags;
char description[1000];
boolean canBeNegated;
} mutation;
typedef struct hordeType {
enum monsterTypes leaderType;
// membership information
short numberOfMemberTypes;
enum monsterTypes memberType[5];
randomRange memberCount[5];
// spawning information
short minLevel;
short maxLevel;
short frequency;
enum tileType spawnsIn;
short machine;
enum hordeFlags flags;
} hordeType;
typedef struct monsterClass {
char name[30];
short frequency;
short maxDepth;
enum monsterTypes memberList[15];
} monsterClass;
typedef struct creature {
creatureType info;
short xLoc;
short yLoc;
short depth;
short currentHP;
long turnsUntilRegen;
short regenPerTurn; // number of HP to regenerate every single turn
short weaknessAmount; // number of points of weakness that are inflicted by the weakness status
short poisonAmount; // number of points of damage per turn from poison
enum creatureStates creatureState; // current behavioral state
enum creatureModes creatureMode; // current behavioral mode (higher-level than state)
short mutationIndex; // what mutation the monster has (or -1 for none)
// Waypoints:
short targetWaypointIndex; // the index number of the waypoint we're pathing toward
boolean waypointAlreadyVisited[MAX_WAYPOINT_COUNT]; // checklist of waypoints
short lastSeenPlayerAt[2]; // last location at which the monster hunted the player
short targetCorpseLoc[2]; // location of the corpse that the monster is approaching to gain its abilities
char targetCorpseName[30]; // name of the deceased monster that we're approaching to gain its abilities
unsigned long absorptionFlags; // ability/behavior flags that the monster will gain when absorption is complete
boolean absorbBehavior; // above flag is behavior instead of ability (ignored if absorptionBolt is set)
short absorptionBolt; // bolt index that the monster will learn to cast when absorption is complete
short corpseAbsorptionCounter; // used to measure both the time until the monster stops being interested in the corpse,
// and, later, the time until the monster finishes absorbing the corpse.
short **mapToMe; // if a pack leader, this is a periodically updated pathing map to get to the leader
short **safetyMap; // fleeing monsters store their own safety map when out of player FOV to avoid omniscience
short ticksUntilTurn; // how long before the creature gets its next move
// Locally cached statistics that may be temporarily modified:
short movementSpeed;
short attackSpeed;
short previousHealthPoints; // remembers what your health proportion was at the start of the turn
short turnsSpentStationary; // how many (subjective) turns it's been since the creature moved between tiles
short flashStrength; // monster will flash soon; this indicates the percent strength of flash
color flashColor; // the color that the monster will flash
short status[NUMBER_OF_STATUS_EFFECTS];
short maxStatus[NUMBER_OF_STATUS_EFFECTS]; // used to set the max point on the status bars
unsigned long bookkeepingFlags;
short spawnDepth; // keep track of the depth of the machine to which they relate (for activation monsters)
short machineHome; // monsters that spawn in a machine keep track of the machine number here (for activation monsters)
short xpxp; // exploration experience (used to time telepathic bonding for allies)
short newPowerCount; // how many more times this monster can absorb a fallen monster
short totalPowerCount; // how many times has the monster been empowered? Used to recover abilities when negated.
struct creature *leader; // only if monster is a follower
struct creature *carriedMonster; // when vampires turn into bats, one of the bats restores the vampire when it dies
struct creature *nextCreature;
struct item *carriedItem; // only used for monsters
} creature;
enum NGCommands {
NG_NOTHING = 0,
NG_NEW_GAME,
NG_NEW_GAME_WITH_SEED,
NG_OPEN_GAME,
NG_VIEW_RECORDING,
NG_HIGH_SCORES,
NG_QUIT,
};
enum featTypes {
FEAT_PURE_MAGE = 0,
FEAT_PURE_WARRIOR,
FEAT_PACIFIST,
FEAT_ARCHIVIST,
FEAT_COMPANION,
FEAT_SPECIALIST,
FEAT_JELLYMANCER,
FEAT_INDOMITABLE,
FEAT_MYSTIC,
FEAT_DRAGONSLAYER,
FEAT_PALADIN,
FEAT_COUNT,
};
// these are basically global variables pertaining to the game state and player's unique variables:
typedef struct playerCharacter {
boolean wizard; // in wizard mode
short depthLevel; // which dungeon level are we on
short deepestLevel;
boolean disturbed; // player should stop auto-acting
boolean gameInProgress; // the game is in progress (the player has not died, won or quit yet)
boolean gameHasEnded; // stop everything and go to death screen
boolean highScoreSaved; // so that it saves the high score only once
boolean blockCombatText; // busy auto-fighting
boolean autoPlayingLevel; // seriously, don't interrupt
boolean automationActive; // cut some corners during redraws to speed things up
boolean justRested; // previous turn was a rest -- used in stealth
boolean justSearched; // previous turn was a search -- used in manual searches
boolean cautiousMode; // used to prevent careless deaths caused by holding down a key
boolean receivedLevitationWarning; // only warn you once when you're hovering dangerously over liquid
boolean updatedSafetyMapThisTurn; // so it's updated no more than once per turn
boolean updatedAllySafetyMapThisTurn; // so it's updated no more than once per turn
boolean updatedMapToSafeTerrainThisTurn;// so it's updated no more than once per turn
boolean updatedMapToShoreThisTurn; // so it's updated no more than once per turn
boolean easyMode; // enables easy mode
boolean inWater; // helps with the blue water filter effect
boolean heardCombatThisTurn; // so you get only one "you hear combat in the distance" per turn
boolean creaturesWillFlashThisTurn; // there are creatures out there that need to flash before the turn ends
boolean staleLoopMap; // recalculate the loop map at the end of the turn
boolean alreadyFell; // so the player can fall only one depth per turn
boolean eligibleToUseStairs; // so the player uses stairs only when he steps onto them
boolean trueColorMode; // whether lighting effects are disabled
boolean displayAggroRangeMode; // whether your stealth range is displayed
boolean quit; // to skip the typical end-game theatrics when the player quits
unsigned long seed; // the master seed for generating the entire dungeon
short RNG; // which RNG are we currently using?
unsigned long gold; // how much gold we have
unsigned long goldGenerated; // how much gold has been generated on the levels, not counting gold held by monsters
short strength;
unsigned short monsterSpawnFuse; // how much longer till a random monster spawns
item *weapon;
item *armor;
item *ringLeft;
item *ringRight;
flare **flares;
short flareCount;
short flareCapacity;
creature *yendorWarden;
lightSource minersLight;
fixpt minersLightRadius;
short ticksTillUpdateEnvironment; // so that some periodic things happen in objective time
unsigned short scentTurnNumber; // helps make scent-casting work
unsigned long playerTurnNumber; // number of input turns in recording. Does not increment during paralysis.
unsigned long absoluteTurnNumber; // number of turns since the beginning of time. Always increments.
signed long milliseconds; // milliseconds since launch, to decide whether to engage cautious mode
short xpxpThisTurn; // how many squares the player explored this turn
short aggroRange; // distance from which monsters will notice you
short previousPoisonPercent; // and your poison proportion, to display percentage alerts for each.
short upLoc[2]; // upstairs location this level
short downLoc[2]; // downstairs location this level
short cursorLoc[2]; // used for the return key functionality
creature *lastTarget; // to keep track of the last monster the player has thrown at or zapped
item *lastItemThrown;
short rewardRoomsGenerated; // to meter the number of reward machines
short machineNumber; // so each machine on a level gets a unique number
short sidebarLocationList[ROWS*2][2]; // to keep track of which location each line of the sidebar references
// maps
short **mapToShore; // how many steps to get back to shore
short **mapToSafeTerrain; // so monsters can get to safety
// recording info
boolean recording; // whether we are recording the game
boolean playbackMode; // whether we're viewing a recording instead of playing
unsigned short patchVersion; // what patch version of the game this was recorded on
char versionString[16]; // the version string saved into the recording file
unsigned long currentTurnNumber; // how many turns have elapsed
unsigned long howManyTurns; // how many turns are in this recording
short howManyDepthChanges; // how many times the player changes depths
short playbackDelayPerTurn; // base playback speed; modified per turn by events
short playbackDelayThisTurn; // playback speed as modified
boolean playbackPaused;
boolean playbackFastForward; // for loading saved games and such -- disables drawing and prevents pauses
boolean playbackOOS; // playback out of sync -- no unpausing allowed
boolean playbackOmniscience; // whether to reveal all the map during playback
boolean playbackBetweenTurns; // i.e. waiting for a top-level input -- iff, permit playback commands
unsigned long nextAnnotationTurn; // the turn number during which to display the next annotation
char nextAnnotation[5000]; // the next annotation
unsigned long locationInAnnotationFile; // how far we've read in the annotations file
// metered items
long long foodSpawned; // amount of nutrition units spawned so far this game
short lifePotionFrequency;
short lifePotionsSpawned;
short strengthPotionFrequency;
short enchantScrollFrequency;
// ring bonuses:
short clairvoyance;
short stealthBonus;
short regenerationBonus;
short lightMultiplier;
short awarenessBonus;
short transference;
short wisdomBonus;
short reaping;
// feats:
boolean featRecord[FEAT_COUNT];
// waypoints:
short **wpDistance[MAX_WAYPOINT_COUNT];
short wpCount;
short wpCoordinates[MAX_WAYPOINT_COUNT][2];
short wpRefreshTicker;
// cursor trail:
short cursorPathIntensity;
boolean cursorMode;
// What do you want to do, player -- play, play with seed, resume, recording, high scores or quit?
enum NGCommands nextGame;
char nextGamePath[BROGUE_FILENAME_MAX];
unsigned long nextGameSeed;
} playerCharacter;
// Stores the necessary info about a level so it can be regenerated:
typedef struct levelData {
boolean visited;
pcell mapStorage[DCOLS][DROWS];
struct item *items;
struct creature *monsters;
struct creature *dormantMonsters;
short **scentMap;
unsigned long levelSeed;
short upStairsLoc[2];
short downStairsLoc[2];
short playerExitedVia[2];
unsigned long awaySince;
} levelData;
enum machineFeatureFlags {
MF_GENERATE_ITEM = Fl(0), // feature entails generating an item (overridden if the machine is adopting an item)
MF_OUTSOURCE_ITEM_TO_MACHINE = Fl(1), // item must be adopted by another machine
MF_BUILD_VESTIBULE = Fl(2), // call this at the origin of a door room to create a new door guard machine there
MF_ADOPT_ITEM = Fl(3), // this feature will take the adopted item (be it from another machine or a previous feature)
MF_NO_THROWING_WEAPONS = Fl(4), // the generated item cannot be a throwing weapon
MF_GENERATE_HORDE = Fl(5), // generate a monster horde that has all of the horde flags
MF_BUILD_AT_ORIGIN = Fl(6), // generate this feature at the room entrance
// unused = Fl(7), //
MF_PERMIT_BLOCKING = Fl(8), // permit the feature to block the map's passability (e.g. to add a locked door)
MF_TREAT_AS_BLOCKING = Fl(9), // treat this terrain as though it blocks, for purposes of deciding whether it can be placed there
MF_NEAR_ORIGIN = Fl(10), // feature must spawn in the rough quarter of tiles closest to the origin
MF_FAR_FROM_ORIGIN = Fl(11), // feature must spawn in the rough quarter of tiles farthest from the origin
MF_MONSTER_TAKE_ITEM = Fl(12), // the item associated with this feature (including if adopted) will be in possession of the horde leader that's generated
MF_MONSTER_SLEEPING = Fl(13), // the monsters should be asleep when generated
MF_MONSTER_FLEEING = Fl(14), // the monsters should be permanently fleeing when generated
MF_EVERYWHERE = Fl(15), // generate the feature on every tile of the machine (e.g. carpeting)
MF_ALTERNATIVE = Fl(16), // build only one feature that has this flag per machine; the rest are skipped
MF_ALTERNATIVE_2 = Fl(17), // same as MF_ALTERNATIVE, but provides for a second set of alternatives of which only one will be chosen
MF_REQUIRE_GOOD_RUNIC = Fl(18), // generated item must be uncursed runic
MF_MONSTERS_DORMANT = Fl(19), // monsters are dormant, and appear when a dungeon feature with DFF_ACTIVATE_DORMANT_MONSTER spawns on their tile
// unused = Fl(20), //
MF_BUILD_IN_WALLS = Fl(21), // build in an impassable tile that is adjacent to the interior
MF_BUILD_ANYWHERE_ON_LEVEL = Fl(22), // build anywhere on the level that is not inside the machine
MF_REPEAT_UNTIL_NO_PROGRESS = Fl(23), // keep trying to build this feature set until no changes are made
MF_IMPREGNABLE = Fl(24), // this feature's location will be immune to tunneling
MF_IN_VIEW_OF_ORIGIN = Fl(25), // this feature must be in view of the origin
MF_IN_PASSABLE_VIEW_OF_ORIGIN = Fl(26), // this feature must be in view of the origin, where "view" is blocked by pathing blockers
MF_NOT_IN_HALLWAY = Fl(27), // the feature location must have a passableArcCount of <= 1
MF_NOT_ON_LEVEL_PERIMETER = Fl(28), // don't build it in the outermost walls of the level
MF_SKELETON_KEY = Fl(29), // if a key is generated or adopted by this feature, it will open all locks in this machine.
MF_KEY_DISPOSABLE = Fl(30), // if a key is generated or adopted, it will self-destruct after being used at this current location.
};
typedef struct machineFeature {
// terrain
enum dungeonFeatureTypes featureDF; // generate this DF at the feature location (0 for none)
enum tileType terrain; // generate this terrain tile at the feature location (0 for none)
enum dungeonLayers layer; // generate the terrain tile in this layer
short instanceCountRange[2]; // generate this range of instances of this feature
short minimumInstanceCount; // abort if fewer than this
// items: these will be ignored if the feature is adopting an item
short itemCategory; // generate this category of item (or -1 for random)
short itemKind; // generate this kind of item (or -1 for random)
short monsterID; // generate a monster of this kind if MF_GENERATE_MONSTER is set
short personalSpace; // subsequent features must be generated more than this many tiles away from this feature
unsigned long hordeFlags; // choose a monster horde based on this
unsigned long itemFlags; // assign these flags to the item
unsigned long flags; // feature flags
} machineFeature;
enum blueprintFlags {
BP_ADOPT_ITEM = Fl(0), // the machine must adopt an item (e.g. a door key)
BP_VESTIBULE = Fl(1), // spawns in a doorway (location must be given) and expands outward, to guard the room
BP_PURGE_PATHING_BLOCKERS = Fl(2), // clean out traps and other T_PATHING_BLOCKERs
BP_PURGE_INTERIOR = Fl(3), // clean out all of the terrain in the interior before generating the machine
BP_PURGE_LIQUIDS = Fl(4), // clean out all of the liquids in the interior before generating the machine
BP_SURROUND_WITH_WALLS = Fl(5), // fill in any impassable gaps in the perimeter (e.g. water, lava, brimstone, traps) with wall
BP_IMPREGNABLE = Fl(6), // impassable perimeter and interior tiles are locked; tunneling bolts will bounce off harmlessly
BP_REWARD = Fl(7), // metered reward machines
BP_OPEN_INTERIOR = Fl(8), // clear out walls in the interior, widen the interior until convex or bumps into surrounding areas
BP_MAXIMIZE_INTERIOR = Fl(9), // same as BP_OPEN_INTERIOR but expands the room as far as it can go, potentially surrounding the whole level.
BP_ROOM = Fl(10), // spawns in a dead-end room that is dominated by a chokepoint of the given size (as opposed to a random place of the given size)
BP_TREAT_AS_BLOCKING = Fl(11), // abort the machine if, were it filled with wall tiles, it would disrupt the level connectivity
BP_REQUIRE_BLOCKING = Fl(12), // abort the machine unless, were it filled with wall tiles, it would disrupt the level connectivity
BP_NO_INTERIOR_FLAG = Fl(13), // don't flag the area as being part of a machine
BP_REDESIGN_INTERIOR = Fl(14), // nuke and pave -- delete all terrain in the interior and build entirely new rooms within the bounds
};
typedef struct blueprint {
short depthRange[2]; // machine must be built between these dungeon depths
short roomSize[2]; // machine must be generated in a room of this size
short frequency; // frequency (number of tickets this blueprint enters in the blueprint selection raffle)
short featureCount; // how many different types of features follow (max of 20)
short dungeonProfileType; // if BP_REDESIGN_INTERIOR is set, which dungeon profile do we use?
unsigned long flags; // blueprint flags
machineFeature feature[20]; // the features themselves
} blueprint;
enum machineTypes {
// Reward rooms:
MT_REWARD_MULTI_LIBRARY = 1,
MT_REWARD_MONO_LIBRARY,
MT_REWARD_CONSUMABLES,
MT_REWARD_PEDESTALS_PERMANENT,
MT_REWARD_PEDESTALS_CONSUMABLE,
MT_REWARD_COMMUTATION_ALTARS,
MT_REWARD_RESURRECTION_ALTAR,
MT_REWARD_ADOPTED_ITEM,
MT_REWARD_DUNGEON,
MT_REWARD_KENNEL,
MT_REWARD_VAMPIRE_LAIR,
MT_REWARD_ASTRAL_PORTAL,
MT_REWARD_GOBLIN_WARREN,
MT_REWARD_SENTINEL_SANCTUARY,
// Amulet holder:
MT_AMULET_AREA,
// Door guard machines:
MT_LOCKED_DOOR_VESTIBULE,
MT_SECRET_DOOR_VESTIBULE,
MT_SECRET_LEVER_VESTIBULE,
MT_FLAMMABLE_BARRICADE_VESTIBULE,
MT_STATUE_SHATTERING_VESTIBULE,
MT_STATUE_MONSTER_VESTIBULE,
MT_THROWING_TUTORIAL_VESTIBULE,
MT_PIT_TRAPS_VESTIBULE,
MT_BECKONING_OBSTACLE_VESTIBULE,
MT_GUARDIAN_VESTIBULE,
// Key guard machines:
MT_KEY_REWARD_LIBRARY,
MT_KEY_SECRET_ROOM,
MT_KEY_THROWING_TUTORIAL_AREA,
MT_KEY_RAT_TRAP_ROOM,
MT_KEY_FIRE_TRANSPORTATION_ROOM,
MT_KEY_FLOOD_TRAP_ROOM,
MT_KEY_FIRE_TRAP_ROOM,
MT_KEY_THIEF_AREA,
MT_KEY_COLLAPSING_FLOOR_AREA,
MT_KEY_PIT_TRAP_ROOM,
MT_KEY_LEVITATION_ROOM,
MT_KEY_WEB_CLIMBING_ROOM,
MT_KEY_LAVA_MOAT_ROOM,
MT_KEY_LAVA_MOAT_AREA,
MT_KEY_POISON_GAS_TRAP_ROOM,
MT_KEY_EXPLOSIVE_TRAP_ROOM,
MT_KEY_BURNING_TRAP_ROOM,
MT_KEY_STATUARY_TRAP_AREA,
MT_KEY_GUARDIAN_WATER_PUZZLE_ROOM,
MT_KEY_GUARDIAN_GAUNTLET_ROOM,
MT_KEY_GUARDIAN_CORRIDOR_ROOM,
MT_KEY_SACRIFICE_ROOM,
MT_KEY_SUMMONING_CIRCLE_ROOM,
MT_KEY_BECKONING_OBSTACLE_ROOM,
MT_KEY_WORM_TRAP_AREA,
MT_KEY_MUD_TRAP_ROOM,
MT_KEY_ELECTRIC_CRYSTALS_ROOM,
MT_KEY_ZOMBIE_TRAP_ROOM,
MT_KEY_PHANTOM_TRAP_ROOM,
MT_KEY_WORM_TUNNEL_ROOM,
MT_KEY_TURRET_TRAP_ROOM,
MT_KEY_BOSS_ROOM,
// Thematic machines:
MT_BLOODFLOWER_AREA,
MT_SHRINE_AREA,
MT_IDYLL_AREA,
MT_SWAMP_AREA,
MT_CAMP_AREA,
MT_REMNANT_AREA,
MT_DISMAL_AREA,
MT_BRIDGE_TURRET_AREA,
MT_LAKE_PATH_TURRET_AREA,
MT_PARALYSIS_TRAP_AREA,
MT_PARALYSIS_TRAP_HIDDEN_AREA,
MT_TRICK_STATUE_AREA,
MT_WORM_AREA,
MT_SENTINEL_AREA,
NUMBER_BLUEPRINTS,
};
typedef struct autoGenerator {
// What spawns:
enum tileType terrain;
enum dungeonLayers layer;
enum dungeonFeatureTypes DFType;
enum machineTypes machine; // Machine placement also respects BP_ placement flags in the machine blueprint
// Parameters governing when and where it spawns:
enum tileType requiredDungeonFoundationType;
enum tileType requiredLiquidFoundationType;
short minDepth;
short maxDepth;
short frequency;
short minNumberIntercept; // actually intercept * 100
short minNumberSlope; // actually slope * 100
short maxNumber;
} autoGenerator;
#define NUMBER_AUTOGENERATORS 49
typedef struct feat {
char name[100];
char description[200];
boolean initialValue;
} feat;
#define PDS_FORBIDDEN -1
#define PDS_OBSTRUCTION -2
#define PDS_CELL(map, x, y) ((map)->links + ((x) + DCOLS * (y)))
typedef struct pdsLink pdsLink;
typedef struct pdsMap pdsMap;
typedef struct brogueButton {
char text[COLS*3]; // button label; can include color escapes
short x; // button's leftmost cell will be drawn at (x, y)
short y;
signed long hotkey[10]; // up to 10 hotkeys to trigger the button
color buttonColor; // background of the button; further gradient-ized when displayed
short opacity; // further reduced by 50% if not enabled
enum displayGlyph symbol[COLS]; // Automatically replace the nth asterisk in the button label text with
// the nth character supplied here, if one is given.
// (Primarily to display magic character and item symbols in the inventory display.)
unsigned long flags;
} brogueButton;
enum buttonDrawStates {
BUTTON_NORMAL = 0,
BUTTON_HOVER,
BUTTON_PRESSED,
};
enum BUTTON_FLAGS {
B_DRAW = Fl(0),
B_ENABLED = Fl(1),
B_GRADIENT = Fl(2),
B_HOVER_ENABLED = Fl(3),
B_WIDE_CLICK_AREA = Fl(4),
B_KEYPRESS_HIGHLIGHT = Fl(5),
};
typedef struct buttonState {
// Indices of the buttons that are doing stuff:
short buttonFocused;
short buttonDepressed;
// Index of the selected button:
short buttonChosen;
// The buttons themselves:
short buttonCount;
brogueButton buttons[50];
// The window location, to determine whether a click is a cancelation:
short winX;
short winY;
short winWidth;
short winHeight;
// Graphical buffers:
cellDisplayBuffer dbuf[COLS][ROWS]; // Where buttons are drawn.
cellDisplayBuffer rbuf[COLS][ROWS]; // Reversion screen state.
} buttonState;
extern boolean serverMode;
extern boolean hasGraphics;
extern boolean graphicsEnabled;
#if defined __cplusplus
extern "C" {
#endif
// Utilities.c - String functions
boolean endswith(const char *str, const char *ending);
void append(char *str, char *ending, int bufsize);
void rogueMain();
void executeEvent(rogueEvent *theEvent);
boolean fileExists(const char *pathname);
boolean chooseFile(char *path, char *prompt, char *defaultName, char *suffix);
boolean openFile(const char *path);
void initializeRogue(unsigned long seed);
void gameOver(char *killedBy, boolean useCustomPhrasing);
void victory(boolean superVictory);
void enableEasyMode();
long rand_range(long lowerBound, long upperBound);
unsigned long seedRandomGenerator(unsigned long seed);
short randClumpedRange(short lowerBound, short upperBound, short clumpFactor);
short randClump(randomRange theRange);
boolean rand_percent(short percent);
void shuffleList(short *list, short listLength);
void fillSequentialList(short *list, short listLength);
fixpt fp_round(fixpt x);
fixpt fp_pow(fixpt base, int expn);
fixpt fp_sqrt(fixpt val);
short unflag(unsigned long flag);
void considerCautiousMode();
void refreshScreen();
void displayLevel();
void storeColorComponents(char components[3], const color *theColor);
boolean separateColors(color *fore, color *back);
void bakeColor(color *theColor);
void shuffleTerrainColors(short percentOfCells, boolean refreshCells);
void normColor(color *baseColor, const short aggregateMultiplier, const short colorTranslation);
void getCellAppearance(short x, short y, enum displayGlyph *returnChar, color *returnForeColor, color *returnBackColor);
void logBuffer(char array[DCOLS][DROWS]);
//void logBuffer(short **array);
boolean search(short searchStrength);
boolean proposeOrConfirmLocation(short x, short y, char *failureMessage);
boolean useStairs(short stairDirection);
short passableArcCount(short x, short y);
void analyzeMap(boolean calculateChokeMap);
boolean buildAMachine(enum machineTypes bp,
short originX, short originY,
unsigned long requiredMachineFlags,
item *adoptiveItem,
item *parentSpawnedItems[50],
creature *parentSpawnedMonsters[50]);
void attachRooms(short **grid, const dungeonProfile *theDP, short attempts, short maxRoomCount);
void digDungeon();
void updateMapToShore();
short levelIsDisconnectedWithBlockingMap(char blockingMap[DCOLS][DROWS], boolean countRegionSize);
void resetDFMessageEligibility();
boolean fillSpawnMap(enum dungeonLayers layer,
enum tileType surfaceTileType,
char spawnMap[DCOLS][DROWS],
boolean blockedByOtherLayers,
boolean refresh,
boolean superpriority);
boolean spawnDungeonFeature(short x, short y, dungeonFeature *feat, boolean refreshCell, boolean abortIfBlocking);
void restoreMonster(creature *monst, short **mapToStairs, short **mapToPit);
void restoreItem(item *theItem);
void refreshWaypoint(short wpIndex);
void setUpWaypoints();
void zeroOutGrid(char grid[DCOLS][DROWS]);
short oppositeDirection(short theDir);
void plotChar(enum displayGlyph inputChar,
short xLoc, short yLoc,
short backRed, short backGreen, short backBlue,
short foreRed, short foreGreen, short foreBlue);
boolean pauseForMilliseconds(short milliseconds);
boolean isApplicationActive();
void nextKeyOrMouseEvent(rogueEvent *returnEvent, boolean textInput, boolean colorsDance);
void notifyEvent(short eventId, int data1, int data2, const char *str1, const char *str2);
boolean takeScreenshot();
boolean setGraphicsEnabled(boolean);
boolean controlKeyIsDown();
boolean shiftKeyIsDown();
short getHighScoresList(rogueHighScoresEntry returnList[HIGH_SCORES_COUNT]);
boolean saveHighScore(rogueHighScoresEntry theEntry);
fileEntry *listFiles(short *fileCount, char **dynamicMemoryBuffer);
void initializeLaunchArguments(enum NGCommands *command, char *path, unsigned long *seed);
char nextKeyPress(boolean textInput);
void refreshSideBar(short focusX, short focusY, boolean focusedEntityMustGoFirst);
void printHelpScreen();
void printDiscoveriesScreen();
void printHighScores(boolean hiliteMostRecent);
void displayGrid(short **map);
void printSeed();
void printProgressBar(short x, short y, const char barLabel[COLS], long amtFilled, long amtMax, color *fillColor, boolean dim);
short printMonsterInfo(creature *monst, short y, boolean dim, boolean highlight);
void describeHallucinatedItem(char *buf);
short printItemInfo(item *theItem, short y, boolean dim, boolean highlight);
short printTerrainInfo(short x, short y, short py, const char *description, boolean dim, boolean highlight);
void rectangularShading(short x, short y, short width, short height,
const color *backColor, short opacity, cellDisplayBuffer dbuf[COLS][ROWS]);
short printTextBox(char *textBuf, short x, short y, short width,
color *foreColor, color *backColor,
cellDisplayBuffer rbuf[COLS][ROWS],
brogueButton *buttons, short buttonCount);
void printMonsterDetails(creature *monst, cellDisplayBuffer rbuf[COLS][ROWS]);
void printFloorItemDetails(item *theItem, cellDisplayBuffer rbuf[COLS][ROWS]);
unsigned long printCarriedItemDetails(item *theItem,
short x, short y, short width,
boolean includeButtons,
cellDisplayBuffer rbuf[COLS][ROWS]);
void funkyFade(cellDisplayBuffer displayBuf[COLS][ROWS], const color *colorStart, const color *colorEnd, short stepCount, short x, short y, boolean invert);
void displayCenteredAlert(char *message);
void flashMessage(char *message, short x, short y, int time, color *fColor, color *bColor);
void flashTemporaryAlert(char *message, int time);
void waitForAcknowledgment();
void waitForKeystrokeOrMouseClick();
boolean confirm(char *prompt, boolean alsoDuringPlayback);
void refreshDungeonCell(short x, short y);
void applyColorMultiplier(color *baseColor, const color *multiplierColor);
void applyColorAverage(color *baseColor, const color *newColor, short averageWeight);
void applyColorAugment(color *baseColor, const color *augmentingColor, short augmentWeight);
void applyColorScalar(color *baseColor, short scalar);
void applyColorBounds(color *baseColor, short lowerBound, short upperBound);
void desaturate(color *baseColor, short weight);
void randomizeColor(color *baseColor, short randomizePercent);
void swapColors(color *color1, color *color2);
void irisFadeBetweenBuffers(cellDisplayBuffer fromBuf[COLS][ROWS],
cellDisplayBuffer toBuf[COLS][ROWS],
short x, short y,
short frameCount,
boolean outsideIn);
void colorBlendCell(short x, short y, color *hiliteColor, short hiliteStrength);
void hiliteCell(short x, short y, const color *hiliteColor, short hiliteStrength, boolean distinctColors);
void colorMultiplierFromDungeonLight(short x, short y, color *editColor);
void plotCharWithColor(enum displayGlyph inputChar, short xLoc, short yLoc, const color *cellForeColor, const color *cellBackColor);
void plotCharToBuffer(enum displayGlyph inputChar, short x, short y, color *foreColor, color *backColor, cellDisplayBuffer dbuf[COLS][ROWS]);
void plotForegroundChar(enum displayGlyph inputChar, short x, short y, color *foreColor, boolean affectedByLighting);
void commitDraws();
void dumpLevelToScreen();
void hiliteCharGrid(char hiliteCharGrid[DCOLS][DROWS], color *hiliteColor, short hiliteStrength);
void blackOutScreen();
void colorOverDungeon(const color *color);
void copyDisplayBuffer(cellDisplayBuffer toBuf[COLS][ROWS], cellDisplayBuffer fromBuf[COLS][ROWS]);
void clearDisplayBuffer(cellDisplayBuffer dbuf[COLS][ROWS]);
color colorFromComponents(char rgb[3]);
void overlayDisplayBuffer(cellDisplayBuffer overBuf[COLS][ROWS], cellDisplayBuffer previousBuf[COLS][ROWS]);
void flashForeground(short *x, short *y, color **flashColor, short *flashStrength, short count, short frames);
void flashCell(color *theColor, short frames, short x, short y);
void colorFlash(const color *theColor, unsigned long reqTerrainFlags, unsigned long reqTileFlags, short frames, short maxRadius, short x, short y);
void printString(const char *theString, short x, short y, color *foreColor, color*backColor, cellDisplayBuffer dbuf[COLS][ROWS]);
short wrapText(char *to, const char *sourceText, short width);
short printStringWithWrapping(char *theString, short x, short y, short width, color *foreColor,
color*backColor, cellDisplayBuffer dbuf[COLS][ROWS]);
boolean getInputTextString(char *inputText,
const char *prompt,
short maxLength,
const char *defaultEntry,
const char *promptSuffix,
short textEntryType,
boolean useDialogBox);
void displayChokeMap();
void displayLoops();
boolean pauseBrogue(short milliseconds);
void nextBrogueEvent(rogueEvent *returnEvent, boolean textInput, boolean colorsDance, boolean realInputEvenInPlayback);
void executeMouseClick(rogueEvent *theEvent);
void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKey);
void initializeLevel();
void startLevel (short oldLevelNumber, short stairDirection);
void updateMinersLightRadius();
void freeCreature(creature *monst);
void emptyGraveyard();
void freeEverything();
boolean randomMatchingLocation(short *x, short *y, short dungeonType, short liquidType, short terrainType);
enum dungeonLayers highestPriorityLayer(short x, short y, boolean skipGas);
enum dungeonLayers layerWithTMFlag(short x, short y, unsigned long flag);
enum dungeonLayers layerWithFlag(short x, short y, unsigned long flag);
char *tileFlavor(short x, short y);
char *tileText(short x, short y);
void describedItemBasedOnParameters(short theCategory, short theKind, short theQuantity, short theItemOriginDepth, char *buf);
void describeLocation(char buf[DCOLS], short x, short y);
void printLocationDescription(short x, short y);
void useKeyAt(item *theItem, short x, short y);
void playerRuns(short direction);
void exposeCreatureToFire(creature *monst);
void updateFlavorText();
void updatePlayerUnderwaterness();
boolean monsterShouldFall(creature *monst);
void applyInstantTileEffectsToCreature(creature *monst);
void vomit(creature *monst);
void becomeAllyWith(creature *monst);
void freeCaptive(creature *monst);
boolean freeCaptivesEmbeddedAt(short x, short y);
boolean handleWhipAttacks(creature *attacker, enum directions dir, boolean *aborted);
boolean handleSpearAttacks(creature *attacker, enum directions dir, boolean *aborted);
boolean diagonalBlocked(const short x1, const short y1, const short x2, const short y2, const boolean limitToPlayerKnowledge);
boolean playerMoves(short direction);
void calculateDistances(short **distanceMap,
short destinationX, short destinationY,
unsigned long blockingTerrainFlags,
creature *traveler,
boolean canUseSecretDoors,
boolean eightWays);
short pathingDistance(short x1, short y1, short x2, short y2, unsigned long blockingTerrainFlags);
short nextStep(short **distanceMap, short x, short y, creature *monst, boolean reverseDirections);
void travelRoute(short path[1000][2], short steps);
void travel(short x, short y, boolean autoConfirm);
void populateGenericCostMap(short **costMap);
void getLocationFlags(const short x, const short y,
unsigned long *tFlags, unsigned long *TMFlags, unsigned long *cellFlags,
const boolean limitToPlayerKnowledge);
void populateCreatureCostMap(short **costMap, creature *monst);
enum directions adjacentFightingDir();
void getExploreMap(short **map, boolean headingToStairs);
boolean explore(short frameDelay);
short getPlayerPathOnMap(short path[1000][2], short **map, short originX, short originY);
void reversePath(short path[1000][2], short steps);
void hilitePath(short path[1000][2], short steps, boolean unhilite);
void clearCursorPath();
void hideCursor();
void showCursor();
void mainInputLoop();
boolean isDisturbed(short x, short y);
void discover(short x, short y);
short randValidDirectionFrom(creature *monst, short x, short y, boolean respectAvoidancePreferences);
boolean exposeTileToElectricity(short x, short y);
boolean exposeTileToFire(short x, short y, boolean alwaysIgnite);
boolean cellCanHoldGas(short x, short y);
void monstersFall();
void updateEnvironment();
void updateAllySafetyMap();
void updateSafetyMap();
void updateSafeTerrainMap();
short staffChargeDuration(const item *theItem);
void rechargeItemsIncrementally(short multiplier);
void extinguishFireOnCreature(creature *monst);
void autoRest();
void manualSearch();
boolean startFighting(enum directions dir, boolean tillDeath);
void autoFight(boolean tillDeath);
void synchronizePlayerTimeState();
void playerRecoversFromAttacking(boolean anAttackHit);
void playerTurnEnded();
void resetScentTurnNumber();
void displayMonsterFlashes(boolean flashingEnabled);
void displayMessageArchive();
void temporaryMessage(char *msg1, boolean requireAcknowledgment);
void messageWithColor(char *msg, color *theColor, boolean requireAcknowledgment);
void flavorMessage(char *msg);
void message(const char *msg, boolean requireAcknowledgment);
void displayMoreSignWithoutWaitingForAcknowledgment();
void displayMoreSign();
short encodeMessageColor(char *msg, short i, const color *theColor);
short decodeMessageColor(const char *msg, short i, color *returnColor);
color *messageColorFromVictim(creature *monst);
void upperCase(char *theChar);
void updateMessageDisplay();
void deleteMessages();
void confirmMessages();
void stripShiftFromMovementKeystroke(signed long *keystroke);
void storeMemories(const short x, const short y);
void updateFieldOfViewDisplay(boolean updateDancingTerrain, boolean refreshDisplay);
void updateFieldOfView(short xLoc, short yLoc, short radius, boolean paintScent,
boolean passThroughCreatures, boolean setFieldOfView, short theColor[3], short fadeToPercent);
void betweenOctant1andN(short *x, short *y, short x0, short y0, short n);
void getFOVMask(char grid[DCOLS][DROWS], short xLoc, short yLoc, fixpt maxRadius,
unsigned long forbiddenTerrain, unsigned long forbiddenFlags, boolean cautiousOnWalls);
void scanOctantFOV(char grid[DCOLS][DROWS], short xLoc, short yLoc, short octant, fixpt maxRadius,
short columnsRightFromOrigin, long startSlope, long endSlope, unsigned long forbiddenTerrain,
unsigned long forbiddenFlags, boolean cautiousOnWalls);
creature *generateMonster(short monsterID, boolean itemPossible, boolean mutationPossible);
short chooseMonster(short forLevel);
creature *spawnHorde(short hordeID, short x, short y, unsigned long forbiddenFlags, unsigned long requiredFlags);
void fadeInMonster(creature *monst);
boolean removeMonsterFromChain(creature *monst, creature *theChain);
boolean monsterWillAttackTarget(const creature *attacker, const creature *defender);
boolean monstersAreTeammates(const creature *monst1, const creature *monst2);
boolean monstersAreEnemies(const creature *monst1, const creature *monst2);
void initializeGender(creature *monst);
boolean stringsMatch(const char *str1, const char *str2);
void resolvePronounEscapes(char *text, creature *monst);
short pickHordeType(short depth, enum monsterTypes summonerType, unsigned long forbiddenFlags, unsigned long requiredFlags);
creature *cloneMonster(creature *monst, boolean announce, boolean placeClone);
void empowerMonster(creature *monst);
unsigned long forbiddenFlagsForMonster(creatureType *monsterType);
unsigned long avoidedFlagsForMonster(creatureType *monsterType);
boolean monsterCanSubmergeNow(creature *monst);
void populateMonsters();
void updateMonsterState(creature *monst);
void decrementMonsterStatus(creature *monst);
boolean specifiedPathBetween(short x1, short y1, short x2, short y2,
unsigned long blockingTerrain, unsigned long blockingFlags);
boolean traversiblePathBetween(creature *monst, short x2, short y2);
boolean openPathBetween(short x1, short y1, short x2, short y2);
creature *monsterAtLoc(short x, short y);
creature *dormantMonsterAtLoc(short x, short y);
void perimeterCoords(short returnCoords[2], short n);
boolean monsterBlinkToPreferenceMap(creature *monst, short **preferenceMap, boolean blinkUphill);
boolean monsterSummons(creature *monst, boolean alwaysUse);
boolean resurrectAlly(const short x, const short y);
void unAlly(creature *monst);
boolean monsterFleesFrom(creature *monst, creature *defender);
void monstersTurn(creature *monst);
boolean getRandomMonsterSpawnLocation(short *x, short *y);
void spawnPeriodicHorde();
void clearStatus(creature *monst);
void moralAttack(creature *attacker, creature *defender);
short runicWeaponChance(item *theItem, boolean customEnchantLevel, fixpt enchantLevel);
void magicWeaponHit(creature *defender, item *theItem, boolean backstabbed);
void teleport(creature *monst, short x, short y, boolean respectTerrainAvoidancePreferences);
void chooseNewWanderDestination(creature *monst);
boolean canPass(creature *mover, creature *blocker);
boolean isPassableOrSecretDoor(short x, short y);
boolean knownToPlayerAsPassableOrSecretDoor(short x, short y);
void setMonsterLocation(creature *monst, short newX, short newY);
boolean moveMonster(creature *monst, short dx, short dy);
unsigned long burnedTerrainFlagsAtLoc(short x, short y);
unsigned long discoveredTerrainFlagsAtLoc(short x, short y);
boolean monsterAvoids(creature *monst, short x, short y);
short distanceBetween(short x1, short y1, short x2, short y2);
void alertMonster(creature *monst);
void wakeUp(creature *monst);
boolean monsterRevealed(creature *monst);
boolean monsterHiddenBySubmersion(const creature *monst, const creature *observer);
boolean monsterIsHidden(const creature *monst, const creature *observer);
boolean canSeeMonster(creature *monst);
boolean canDirectlySeeMonster(creature *monst);
void monsterName(char *buf, creature *monst, boolean includeArticle);
boolean monsterIsInClass(const creature *monst, const short monsterClass);
fixpt strengthModifier(item *theItem);
fixpt netEnchant(item *theItem);
short hitProbability(creature *attacker, creature *defender);
boolean attackHit(creature *attacker, creature *defender);
void applyArmorRunicEffect(char returnString[DCOLS], creature *attacker, short *damage, boolean melee);
void processStaggerHit(creature *attacker, creature *defender);
boolean attack(creature *attacker, creature *defender, boolean lungeAttack);
void inflictLethalDamage(creature *attacker, creature *defender);
boolean inflictDamage(creature *attacker, creature *defender,
short damage, const color *flashColor, boolean ignoresProtectionShield);
void addPoison(creature *monst, short totalDamage, short concentrationIncrement);
void killCreature(creature *decedent, boolean administrativeDeath);
void buildHitList(creature **hitList, const creature *attacker, creature *defender, const boolean sweep);
void addScentToCell(short x, short y, short distance);
void populateItems(short upstairsX, short upstairsY);
item *placeItem(item *theItem, short x, short y);
void removeItemFrom(short x, short y);
void pickUpItemAt(short x, short y);
item *addItemToPack(item *theItem);
void aggravateMonsters(short distance, short x, short y, const color *flashColor);
short getLineCoordinates(short listOfCoordinates[][2], const short originLoc[2], const short targetLoc[2]);
void getImpactLoc(short returnLoc[2], const short originLoc[2], const short targetLoc[2],
const short maxDistance, const boolean returnLastEmptySpace);
void negate(creature *monst);
short monsterAccuracyAdjusted(const creature *monst);
fixpt monsterDamageAdjustmentAmount(const creature *monst);
short monsterDefenseAdjusted(const creature *monst);
void weaken(creature *monst, short maxDuration);
void slow(creature *monst, short turns);
void haste(creature *monst, short turns);
void heal(creature *monst, short percent, boolean panacea);
boolean projectileReflects(creature *attacker, creature *defender);
short reflectBolt(short targetX, short targetY, short listOfCoordinates[][2], short kinkCell, boolean retracePath);
void checkForMissingKeys(short x, short y);
enum boltEffects boltEffectForItem(item *theItem);
enum boltType boltForItem(item *theItem);
boolean zap(short originLoc[2], short targetLoc[2], bolt *theBolt, boolean hideDetails);
boolean nextTargetAfter(short *returnX,
short *returnY,
short targetX,
short targetY,
boolean targetEnemies,
boolean targetAllies,
boolean targetItems,
boolean targetTerrain,
boolean requireOpenPath,
boolean reverseDirection);
boolean moveCursor(boolean *targetConfirmed,
boolean *canceled,
boolean *tabKey,
short targetLoc[2],
rogueEvent *event,
buttonState *state,
boolean colorsDance,
boolean keysMoveCursor,
boolean targetCanLeaveMap);
void identifyItemKind(item *theItem);
void autoIdentify(item *theItem);
short numberOfItemsInPack();
char nextAvailableInventoryCharacter();
void checkForDisenchantment(item *theItem);
void updateFloorItems();
void itemKindName(item *theItem, char *kindName);
void itemRunicName(item *theItem, char *runicName);
void itemName(item *theItem, char *root, boolean includeDetails, boolean includeArticle, color *baseColor);
char displayInventory(unsigned short categoryMask,
unsigned long requiredFlags,
unsigned long forbiddenFlags,
boolean waitForAcknowledge,
boolean includeButtons);
short numberOfMatchingPackItems(unsigned short categoryMask,
unsigned long requiredFlags, unsigned long forbiddenFlags,
boolean displayErrors);
void clearInventory(char keystroke);
item *initializeItem();
item *generateItem(unsigned short theCategory, short theKind);
short chooseKind(itemTable *theTable, short numKinds);
item *makeItemInto(item *theItem, unsigned long itemCategory, short itemKind);
void updateEncumbrance();
short displayedArmorValue();
void strengthCheck(item *theItem);
void recalculateEquipmentBonuses();
void equipItem(item *theItem, boolean force);
void equip(item *theItem);
item *keyInPackFor(short x, short y);
item *keyOnTileAt(short x, short y);
void unequip(item *theItem);
void drop(item *theItem);
void findAlternativeHomeFor(creature *monst, short *x, short *y, boolean chooseRandomly);
boolean getQualifyingLocNear(short loc[2],
short x, short y,
boolean hallwaysAllowed,
char blockingMap[DCOLS][DROWS],
unsigned long forbiddenTerrainFlags,
unsigned long forbiddenMapFlags,
boolean forbidLiquid,
boolean deterministic);
boolean getQualifyingGridLocNear(short loc[2],
short x, short y,
boolean grid[DCOLS][DROWS],
boolean deterministic);
// Grid operations
short **allocGrid();
void freeGrid(short **array);
void copyGrid(short **to, short **from);
void fillGrid(short **grid, short fillValue);
void hiliteGrid(short **grid, color *hiliteColor, short hiliteStrength);
void findReplaceGrid(short **grid, short findValueMin, short findValueMax, short fillValue);
short floodFillGrid(short **grid, short x, short y, short eligibleValueMin, short eligibleValueMax, short fillValue);
void drawRectangleOnGrid(short **grid, short x, short y, short width, short height, short value);
void drawCircleOnGrid(short **grid, short x, short y, short radius, short value);
void getTerrainGrid(short **grid, short value, unsigned long terrainFlags, unsigned long mapFlags);
void getTMGrid(short **grid, short value, unsigned long TMflags);
short validLocationCount(short **grid, short validValue);
void randomLocationInGrid(short **grid, short *x, short *y, short validValue);
boolean getQualifyingPathLocNear(short *retValX, short *retValY,
short x, short y,
boolean hallwaysAllowed,
unsigned long blockingTerrainFlags,
unsigned long blockingMapFlags,
unsigned long forbiddenTerrainFlags,
unsigned long forbiddenMapFlags,
boolean deterministic);
void createBlobOnGrid(short **grid,
short *retMinX, short *retMinY, short *retWidth, short *retHeight,
short roundCount,
short minBlobWidth, short minBlobHeight,
short maxBlobWidth, short maxBlobHeight, short percentSeeded,
char birthParameters[9], char survivalParameters[9]);
void checkForContinuedLeadership(creature *monst);
void demoteMonsterFromLeadership(creature *monst);
void toggleMonsterDormancy(creature *monst);
void monsterDetails(char buf[], creature *monst);
void makeMonsterDropItem(creature *monst);
void throwCommand(item *theItem, boolean autoThrow);
void relabel(item *theItem);
void apply(item *theItem, boolean recordCommands);
boolean itemCanBeCalled(item *theItem);
void call(item *theItem);
short chooseVorpalEnemy();
void describeMonsterClass(char *buf, const short classID, boolean conjunctionAnd);
void identify(item *theItem);
void updateIdentifiableItem(item *theItem);
void updateIdentifiableItems();
void readScroll(item *theItem);
void updateRingBonuses();
void updatePlayerRegenerationDelay();
boolean removeItemFromChain(item *theItem, item *theChain);
void addItemToChain(item *theItem, item *theChain);
void drinkPotion(item *theItem);
item *promptForItemOfType(unsigned short category,
unsigned long requiredFlags,
unsigned long forbiddenFlags,
char *prompt,
boolean allowInventoryActions);
item *itemOfPackLetter(char letter);
void unequipItem(item *theItem, boolean force);
short magicCharDiscoverySuffix(short category, short kind);
int itemMagicPolarity(item *theItem);
item *itemAtLoc(short x, short y);
item *dropItem(item *theItem);
itemTable *tableForItemCategory(enum itemCategory theCat, short *kindCount);
boolean isVowelish(char *theChar);
short charmEffectDuration(short charmKind, short enchant);
short charmRechargeDelay(short charmKind, short enchant);
boolean itemIsCarried(item *theItem);
void itemDetails(char *buf, item *theItem);
void deleteItem(item *theItem);
void shuffleFlavors();
unsigned long itemValue(item *theItem);
short strLenWithoutEscapes(const char *str);
void combatMessage(char *theMsg, color *theColor);
void displayCombatText();
void flashMonster(creature *monst, const color *theColor, short strength);
boolean paintLight(lightSource *theLight, short x, short y, boolean isMinersLight, boolean maintainShadows);
void backUpLighting(short lights[DCOLS][DROWS][3]);
void restoreLighting(short lights[DCOLS][DROWS][3]);
void updateLighting();
boolean playerInDarkness();
flare *newFlare(lightSource *light, short x, short y, short changePerFrame, short limit);
void createFlare(short x, short y, enum lightType lightIndex);
void animateFlares(flare **flares, short count);
void deleteAllFlares();
void demoteVisibility();
void discoverCell(const short x, const short y);
void updateVision(boolean refreshDisplay);
void burnItem(item *theItem);
void activateMachine(short machineNumber);
boolean circuitBreakersPreventActivation(short machineNumber);
void promoteTile(short x, short y, enum dungeonLayers layer, boolean useFireDF);
void autoPlayLevel(boolean fastForward);
void updateClairvoyance();
short scentDistance(short x1, short y1, short x2, short y2);
short armorAggroAdjustment(item *theArmor);
short currentAggroValue();
void initRecording();
void flushBufferToFile();
void fillBufferFromFile();
void recordEvent(rogueEvent *event);
void recallEvent(rogueEvent *event);
void pausePlayback();
void displayAnnotation();
boolean loadSavedGame();
void switchToPlaying();
void recordKeystroke(int keystroke, boolean controlKey, boolean shiftKey);
void recordKeystrokeSequence(unsigned char *commandSequence);
void recordMouseClick(short x, short y, boolean controlKey, boolean shiftKey);
void OOSCheck(unsigned long x, short numberOfBytes);
void RNGCheck();
boolean executePlaybackInput(rogueEvent *recordingInput);
void getAvailableFilePath(char *filePath, const char *defaultPath, const char *suffix);
boolean characterForbiddenInFilename(const char theChar);
void saveGame();
void saveGameNoPrompt();
void saveRecording(char *filePath);
void saveRecordingNoPrompt(char *filePath);
void parseFile();
void RNGLog(char *message);
short wandDominate(creature *monst);
short staffDamageLow(fixpt enchant);
short staffDamageHigh(fixpt enchant);
short staffDamage(fixpt enchant);
int staffPoison(fixpt enchant);
short staffBlinkDistance(fixpt enchant);
short staffHasteDuration(fixpt enchant);
short staffBladeCount(fixpt enchant);
short staffDiscordDuration(fixpt enchant);
int staffProtection(fixpt enchant);
short staffEntrancementDuration(fixpt enchant);
fixpt ringWisdomMultiplier(fixpt enchant);
short charmHealing(fixpt enchant);
int charmProtection(fixpt enchant);
short charmShattering(fixpt enchant);
short charmGuardianLifespan(fixpt enchant);
short charmNegationRadius(fixpt enchant);
short weaponParalysisDuration(fixpt enchant);
short weaponConfusionDuration(fixpt enchant);
short weaponForceDistance(fixpt enchant);
short weaponSlowDuration(fixpt enchant);
short weaponImageCount(fixpt enchant);
short weaponImageDuration(fixpt enchant);
short armorReprisalPercent(fixpt enchant);
short armorAbsorptionMax(fixpt enchant);
short armorImageCount(fixpt enchant);
short reflectionChance(fixpt enchant);
long turnsForFullRegenInThousandths(fixpt bonus);
fixpt damageFraction(fixpt netEnchant);
fixpt accuracyFraction(fixpt netEnchant);
fixpt defenseFraction(fixpt netDefense);
void checkForDungeonErrors();
boolean dialogChooseFile(char *path, const char *suffix, const char *prompt);
void quitImmediately();
void dialogAlert(char *message);
void mainBrogueJunction();
void printSeedCatalog(unsigned long startingSeed, unsigned long numberOfSeedsToScan, unsigned int scanThroughDepth, boolean isCsvFormat);
void initializeButton(brogueButton *button);
void drawButtonsInState(buttonState *state);
void initializeButtonState(buttonState *state,
brogueButton *buttons,
short buttonCount,
short winX,
short winY,
short winWidth,
short winHeight);
short processButtonInput(buttonState *state, boolean *canceled, rogueEvent *event);
short smoothHiliteGradient(const short currentXValue, const short maxXValue);
void drawButton(brogueButton *button, enum buttonDrawStates highlight, cellDisplayBuffer dbuf[COLS][ROWS]);
short buttonInputLoop(brogueButton *buttons,
short buttonCount,
short winX,
short winY,
short winWidth,
short winHeight,
rogueEvent *returnEvent);
void dijkstraScan(short **distanceMap, short **costMap, boolean useDiagonals);
void pdsClear(pdsMap *map, short maxDistance, boolean eightWays);
void pdsSetDistance(pdsMap *map, short x, short y, short distance);
void pdsBatchOutput(pdsMap *map, short **distanceMap);
#if defined __cplusplus
}
#endif