// // 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 . // #include #include #include #include #include #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 #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