/* * File: command.cc * Summary: Misc commands. * Written by: Linley Henzell * * Modified for Crawl Reference by $Author$ on $Date$ * * Change History (most recent first): * * <4> 10/12/99 BCR BUILD_DATE is now used in version() * <3> 6/13/99 BWR New equipment listing commands * <2> 5/20/99 BWR Swapping inventory letters. * <1> -/--/-- LRH Created */ #include "AppHdr.h" #include "command.h" #include #include #include #include "externs.h" #include "abl-show.h" #include "chardump.h" #include "files.h" #include "invent.h" #include "itemname.h" #include "item_use.h" #include "items.h" #include "libutil.h" #include "menu.h" #include "ouch.h" #include "spl-cast.h" #include "spl-util.h" #include "stuff.h" #include "version.h" #include "view.h" static void adjust_item(void); static void adjust_spells(void); static void adjust_ability(void); static void list_wizard_commands(); #ifdef OBSOLETE_COMMAND_HELP static const char *command_string( int i ); #endif static const char *wizard_string( int i ); void quit_game(void) { if (yesno("Really quit?", false, 'n')) ouch(INSTANT_DEATH, 0, KILLED_BY_QUITTING); } // end quit_game() static const char *features[] = { "", "Stash-tracking", #ifdef CLUA_BINDINGS "Lua", #endif #if defined(REGEX_POSIX) "POSIX regexps", #elif defined(REGEX_PCRE) "PCRE regexps", #else "Glob patterns", #endif }; void version(void) { mpr( "This is " CRAWL " " VERSION " (" BUILD_DATE ")." ); std::string feats = "Features: "; for (int i = 1, size = sizeof features / sizeof *features; i < size; ++i) { if (i > 1) feats += ", "; feats += features[i]; } mpr(feats.c_str()); } // end version() void adjust(void) { mpr( "Adjust (i)tems, (s)pells, or (a)bilities?", MSGCH_PROMPT ); unsigned char keyin = tolower( get_ch() ); if (keyin == 'i') adjust_item(); else if (keyin == 's') adjust_spells(); else if (keyin == 'a') adjust_ability(); else if (keyin == ESCAPE) canned_msg( MSG_OK ); else canned_msg( MSG_HUH ); } // end adjust() void swap_inv_slots(int from_slot, int to_slot, bool verbose) { // swap items item_def tmp = you.inv[to_slot]; you.inv[to_slot] = you.inv[from_slot]; you.inv[from_slot] = tmp; you.inv[from_slot].link = from_slot; you.inv[to_slot].link = to_slot; for (int i = 0; i < NUM_EQUIP; i++) { if (you.equip[i] == from_slot) you.equip[i] = to_slot; else if (you.equip[i] == to_slot) you.equip[i] = from_slot; } if (verbose) { char str_pass[ ITEMNAME_SIZE ]; in_name( to_slot, DESC_INVENTORY_EQUIP, str_pass ); mpr( str_pass ); if (is_valid_item( you.inv[from_slot] )) { in_name( from_slot, DESC_INVENTORY_EQUIP, str_pass ); mpr( str_pass ); } } if (to_slot == you.equip[EQ_WEAPON] || from_slot == you.equip[EQ_WEAPON]) you.wield_change = true; } static void adjust_item(void) { int from_slot, to_slot; char str_pass[ ITEMNAME_SIZE ]; if (inv_count() < 1) { canned_msg(MSG_NOTHING_CARRIED); return; } from_slot = prompt_invent_item( "Adjust which item?", MT_INVSELECT, -1 ); if (from_slot == PROMPT_ABORT) { canned_msg( MSG_OK ); return; } in_name( from_slot, DESC_INVENTORY_EQUIP, str_pass ); mpr( str_pass ); to_slot = prompt_invent_item( "Adjust to which letter?", MT_INVSELECT, -1, false, false ); if (to_slot == PROMPT_ABORT) { canned_msg( MSG_OK ); return; } swap_inv_slots(from_slot, to_slot, true); } // end adjust_item() static void adjust_spells_cleanup(bool needs_redraw) { if (needs_redraw) redraw_screen(); } static void adjust_spells(void) { unsigned char index_1, index_2; unsigned char nthing = 0; bool needs_redraw = false; if (!you.spell_no) { mpr("You don't know any spells."); return; } query: mpr("Adjust which spell?", MSGCH_PROMPT); unsigned char keyin = get_ch(); if (keyin == '?' || keyin == '*') { if (keyin == '*' || keyin == '?') { nthing = list_spells(); needs_redraw = true; } if (isalpha( nthing ) || nthing == ESCAPE) keyin = nthing; else { mesclr( true ); goto query; } } if (keyin == ESCAPE) { adjust_spells_cleanup(needs_redraw); canned_msg( MSG_OK ); return; } int input_1 = (int) keyin; if (!isalpha( input_1 )) { adjust_spells_cleanup(needs_redraw); mpr("You don't know that spell."); return; } index_1 = letter_to_index( input_1 ); int spell = get_spell_by_letter( input_1 ); if (spell == SPELL_NO_SPELL) { adjust_spells_cleanup(needs_redraw); mpr("You don't know that spell."); return; } // print out targeted spell: snprintf( info, INFO_SIZE, "%c - %s", input_1, spell_title( spell ) ); mpr(info); mpr( "Adjust to which letter?", MSGCH_PROMPT ); keyin = get_ch(); if (keyin == '?' || keyin == '*') { if (keyin == '*' || keyin == '?') { nthing = list_spells(); needs_redraw = true; } if (isalpha( nthing ) || nthing == ESCAPE) keyin = nthing; else { mesclr( true ); goto query; } } if (keyin == ESCAPE) { adjust_spells_cleanup(needs_redraw); canned_msg( MSG_OK ); return; } int input_2 = (int) keyin; if (!isalpha( input_2 )) { adjust_spells_cleanup(needs_redraw); mpr("What?"); return; } adjust_spells_cleanup(needs_redraw); index_2 = letter_to_index( input_2 ); // swap references in the letter table: int tmp = you.spell_letter_table[index_2]; you.spell_letter_table[index_2] = you.spell_letter_table[index_1]; you.spell_letter_table[index_1] = tmp; // print out spell in new slot (now at input_2) snprintf( info, INFO_SIZE, "%c - %s", input_2, spell_title( get_spell_by_letter(input_2) ) ); mpr(info); // print out other spell if one was involved (now at input_1) spell = get_spell_by_letter( input_1 ); if (spell != SPELL_NO_SPELL) { snprintf( info, INFO_SIZE, "%c - %s", input_1, spell_title(spell) ); mpr(info); } } // end adjust_spells() static void adjust_ability(void) { unsigned char index_1, index_2; unsigned char nthing = 0; bool needs_redraw = false; if (!generate_abilities()) { mpr( "You don't currently have any abilities." ); return; } query: mpr( "Adjust which ability?", MSGCH_PROMPT ); unsigned char keyin = get_ch(); if (keyin == '?' || keyin == '*') { if (keyin == '*' || keyin == '?') { nthing = show_abilities(); needs_redraw = true; } if (isalpha( nthing ) || nthing == ESCAPE) keyin = nthing; else { mesclr( true ); goto query; } } if (keyin == ESCAPE) { adjust_spells_cleanup(needs_redraw); canned_msg( MSG_OK ); return; } int input_1 = (int) keyin; if (!isalpha( input_1 )) { adjust_spells_cleanup(needs_redraw); mpr("You don't have that ability."); return; } index_1 = letter_to_index( input_1 ); if (you.ability_letter_table[index_1] == ABIL_NON_ABILITY) { adjust_spells_cleanup(needs_redraw); mpr("You don't have that ability."); return; } // print out targeted spell: snprintf( info, INFO_SIZE, "%c - %s", input_1, get_ability_name_by_index( index_1 ) ); mpr(info); mpr( "Adjust to which letter?", MSGCH_PROMPT ); keyin = get_ch(); if (keyin == '?' || keyin == '*') { if (keyin == '*' || keyin == '?') { nthing = show_abilities(); needs_redraw = true; } if (isalpha( nthing ) || nthing == ESCAPE) keyin = nthing; else { mesclr( true ); goto query; } } if (keyin == ESCAPE) { adjust_spells_cleanup(needs_redraw); canned_msg( MSG_OK ); return; } int input_2 = (int) keyin; if (!isalpha( input_2 )) { adjust_spells_cleanup(needs_redraw); mpr("What?"); return; } adjust_spells_cleanup(needs_redraw); index_2 = letter_to_index( input_2 ); // swap references in the letter table: int tmp = you.ability_letter_table[index_2]; you.ability_letter_table[index_2] = you.ability_letter_table[index_1]; you.ability_letter_table[index_1] = tmp; // Note: the input_2/index_1 and input_1/index_2 here is intentional. // This is because nothing actually moves until generate_abilities is // called again... fortunately that has to be done everytime because // that's the silly way this system currently works. -- bwr snprintf( info, INFO_SIZE, "%c - %s", input_2, get_ability_name_by_index( index_1 ) ); mpr(info); if (you.ability_letter_table[index_1] != ABIL_NON_ABILITY) { snprintf( info, INFO_SIZE, "%c - %s", input_1, get_ability_name_by_index( index_2 ) ); mpr(info); } } // end adjust_ability() void list_armour(void) { for (int i = EQ_CLOAK; i <= EQ_BODY_ARMOUR; i++) { int armour_id = you.equip[i]; strcpy( info, (i == EQ_CLOAK) ? "Cloak " : (i == EQ_HELMET) ? "Helmet " : (i == EQ_GLOVES) ? "Gloves " : (i == EQ_SHIELD) ? "Shield " : (i == EQ_BODY_ARMOUR) ? "Armour " : (i == EQ_BOOTS && !(you.species == SP_CENTAUR || you.species == SP_NAGA)) ? "Boots " : (i == EQ_BOOTS && (you.species == SP_CENTAUR || you.species == SP_NAGA)) ? "Barding" : "unknown" ); strcat(info, " : "); if (armour_id != -1) { char str_pass[ ITEMNAME_SIZE ]; in_name(armour_id, DESC_INVENTORY, str_pass); strcat(info, str_pass); } else { strcat(info, " none"); } mpr( info, MSGCH_EQUIPMENT, menu_colour(info) ); } } // end list_armour() void list_jewellery(void) { for (int i = EQ_LEFT_RING; i <= EQ_AMULET; i++) { int jewellery_id = you.equip[i]; strcpy( info, (i == EQ_LEFT_RING) ? "Left ring " : (i == EQ_RIGHT_RING) ? "Right ring" : (i == EQ_AMULET) ? "Amulet " : "unknown " ); strcat(info, " : "); if (jewellery_id != -1) { char str_pass[ ITEMNAME_SIZE ]; in_name(jewellery_id, DESC_INVENTORY, str_pass); strcat(info, str_pass); } else { strcat(info, " none"); } mpr( info, MSGCH_EQUIPMENT, menu_colour(info) ); } } // end list_jewellery() void list_weapons(void) { const int weapon_id = you.equip[EQ_WEAPON]; // Output the current weapon // // Yes, this is already on the screen... I'm outputing it // for completeness and to avoid confusion. strcpy(info, "Current : "); if (weapon_id != -1) { char str_pass[ ITEMNAME_SIZE ]; in_name( weapon_id, DESC_INVENTORY_EQUIP, str_pass ); strcat(info, str_pass); } else { if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS) strcat(info, " blade hands"); else strcat(info, " empty hands"); } mpr(info, MSGCH_EQUIPMENT, menu_colour(info)); // Print out the swap slots for (int i = 0; i <= 1; i++) { // We'll avoid repeating the current weapon for these slots, // in order to keep things clean. if (weapon_id == i) continue; strcpy(info, (i == 0) ? "Primary : " : "Secondary : "); if (is_valid_item( you.inv[i] )) { char str_pass[ ITEMNAME_SIZE ]; in_name(i, DESC_INVENTORY_EQUIP, str_pass); strcat(info, str_pass); } else strcat(info, " none"); mpr(info, MSGCH_EQUIPMENT, menu_colour(info)); // Output slot } // Now we print out the current default fire weapon strcpy(info, "Firing : "); const int item = get_fire_item_index(); if (item == ENDOFPACK) strcat(info, " nothing"); else { char str_pass[ ITEMNAME_SIZE ]; in_name( item, DESC_INVENTORY_EQUIP, str_pass ); strcat( info, str_pass ); } mpr( info, MSGCH_EQUIPMENT, menu_colour(info) ); } // end list_weapons() static bool cmdhelp_textfilter(const std::string &tag) { #ifdef WIZARD if (tag == "wiz") return (true); #endif return (false); } static const char *level_map_help = "Level Map ('X' in main screen):\n" "Esc : leave level map (also Space)\n" "Dir.: move cursor\n" "/ Dir., Shift-Dir.: move cursor far\n" "-/+ : scroll level map up/down\n" ". : travel (also Enter and , and ;)\n" " (moves cursor to last travel\n" " destination if still on @)\n" "<</> : cycle through up/down stairs\n" "^ : cycle through traps\n" "Tab : cycle through shops and portals\n" "X : cycle through travel eXclusions\n" "W : cycle through waypoints\n" "* : cycle forward through stashes\n" "/ : cycle backward through stashes\n" "_ : cycle through altars\n" "Ctrl-X : set travel eXclusion\n" "Ctrl-E : Erase all travel exclusions\n" "Ctrl-W : set Waypoint\n" "Ctrl-C : Clear level and main maps\n"; static const char *targeting_help = "Targeting (like zapping wands/spells):\n" "Dir : move in that direction\n" "Shift-Dir : shoot straight-line beam\n" "Space : cycle through beams\n" ": : hide beam\n" "Esc : cancel targeting\n" "Ctrl-F : cycle monster cycle mode\n" "p : fire at Previous target (also t, f)\n" "+ : cycle monsters forward (also =)\n" "- : cycle monsters backward\n" ". : fire at target (also Enter or Del)\n" "! : fire at target and stop there\n" "; : cycle objects forward\n" "/ : cycle objects backward\n" "v : describe monster under cursor\n" "<</> : cycle through up/down stairs\n" "^ : cycle through traps\n" "Tab : cycle through shops and portals\n" "_ : cycle through altars\n" "? : targeting help\n"; // Add the contents of the file fp to the scroller menu m. // If first_hotkey is nonzero, that will be the hotkey for the // start of the contents of the file. // If auto_hotkeys is true, the function will try to identify // sections and add appropriate hotkeys. static void add_file_to_scroller(FILE* fp, formatted_scroller& m, int first_hotkey, bool auto_hotkeys ) { bool next_is_hotkey = false; bool is_first = true; char buf[200]; // bracket with MEL_TITLES, so that you won't scroll // into it or above it m.add_entry(new MenuEntry(std::string(), MEL_TITLE)); for ( int i = 0; i < get_number_of_lines(); ++i ) m.add_entry(new MenuEntry(std::string())); m.add_entry(new MenuEntry(std::string(), MEL_TITLE)); while (fgets(buf, sizeof buf, fp)) { MenuEntry* me = new MenuEntry(buf); if ((next_is_hotkey && isupper(buf[0])) || (is_first && first_hotkey)) { me->add_hotkey(is_first ? first_hotkey : tolower(buf[0])); me->level = MEL_SUBTITLE; me->colour = WHITE; } m.add_entry(me); // XXX FIXME: there must be a better way to identify sections next_is_hotkey = auto_hotkeys && (strstr(buf, "------------------------------------------" "------------------------------") == buf); is_first = false; } } struct help_file { const char* name; int hotkey; bool auto_hotkey; }; help_file help_files[] = { { "crawl_manual.txt", '*', true }, { "tables.txt", '%', false }, { "readme.txt", '^', false }, { "crawl_macros.txt", '~', false }, { NULL, 0, false } }; static int keyhelp_keyfilter(int ch) { switch (ch) { case ':': display_notes(); return -1; default: return ch; } } static void show_keyhelp_menu(const std::vector &lines, bool with_manual) { formatted_scroller cmd_help; // Set flags, and don't use easy exit. cmd_help.set_flags(MF_NOSELECT | MF_ALWAYS_SHOW_MORE | MF_NOWRAP, false); // FIXME: Allow for hiding Page down when at the end of the listing, ditto // for page up at start of listing. cmd_help.set_more( formatted_string::parse_string( "[ + : Page down. - : Page up." " Esc exits.]")); if ( with_manual ) { cmd_help.f_keyfilter = keyhelp_keyfilter; column_composer cols(1); cols.add_formatted( 0, "Dungeon Crawl Help\n" "\n" "Press one of the following keys to obtain more information on a certain\n" "aspect of Dungeon Crawl.\n" "?: Key Help Screens\n" "*: Read the manual\n" "^: Quickstart Guide\n" ":: Browse Notes\n" "~: Macros help\n" "%: Table of Aptitudes\n", true, true, cmdhelp_textfilter); std::vector blines = cols.formatted_lines(); unsigned i; for (i = 0; i < blines.size(); ++i ) cmd_help.add_item_formatted_string(blines[i]); while ( static_cast(++i) < get_number_of_lines() ) cmd_help.add_item_string(""); } for (unsigned i = 0; i < lines.size(); ++i ) cmd_help.add_item_formatted_string(lines[i], (i == 0 ? '?' : 0) ); if ( with_manual ) { for ( int i = 0; help_files[i].name != NULL; ++i ) { FILE* fp = fopen( datafile_path(help_files[i].name, false).c_str(), "r"); if ( !fp ) continue; // put in a separator cmd_help.add_item_string(""); cmd_help.add_item_string(std::string(get_number_of_cols()-1,'=')); cmd_help.add_item_string(""); // and the file itself add_file_to_scroller(fp, cmd_help, help_files[i].hotkey, help_files[i].auto_hotkey); // done with this file fclose(fp); } } cmd_help.show(); } void show_specific_help( const char* help ) { std::vector lines = split_string("\n", help, false, true); std::vector formatted_lines; for (int i = 0, size = lines.size(); i < size; ++i) formatted_lines.push_back( formatted_string::parse_string( lines[i], true, cmdhelp_textfilter)); show_keyhelp_menu(formatted_lines, false); } void show_levelmap_help() { show_specific_help( level_map_help ); } void show_targeting_help() { show_specific_help( targeting_help ); } void list_commands(bool wizard) { if (wizard) { list_wizard_commands(); return; } // 2 columns, split at column 40. column_composer cols(2, 41); // Page size is number of lines - one line for --more-- prompt. cols.set_pagesize(get_number_of_lines() - 1); cols.add_formatted( 0, "Movement:\n" "To move in a direction or to attack, use\n" "the numpad (try Numlock both off and on)\n" "or vi keys:\n" " 1 2 3 y k u\n" " \\|/ \\|/\n" " 4-5-6" " h-.-l\n" " /|\\ /|\\\n" " 7 8 9 b j n\n", true, true, cmdhelp_textfilter); cols.add_formatted( 0, "Rest/Search:\n" "s : rest one turn and search adjacent\n" " squares (also numpad-5, ., Del)\n" "5 : fully rest HP/MP or search; stop after \n" " 100 turns (also Shift-numpad-5)\n", true, true, cmdhelp_textfilter); cols.add_formatted( 0, "Extended Movement:\n" "/ Dir., Shift-Dir.: long walk\n" "* Dir., Ctrl-Dir. : untrap, attack\n" " without move, open door\n" "Ctrl-G : interlevel travel\n" "Ctrl-O : auto-explore\n" "Ctrl-W : set Waypoint\n" "Ctrl-F : Find items\n", true, true, cmdhelp_textfilter); cols.add_formatted( 0, "Item Interaction (inventory):\n" "i : show Inventory list\n" "v : View item description\n" "{ : inscribe item\n" "t : Throw/shoot an item\n" "f : Fire first available missile\n" "e : Eat food (but tries floor first)\n" "q : Quaff a potion\n" "z : Zap a wand\n" "r : Read a scroll or book\n" "M : Memorise a spell from a book\n" "w : Wield an item ( - for none)\n" "' : wield item a, or switch to b\n" "E : Evoke power of wielded item\n" "W : Wear armour\n" "T : Take off armour\n" "P : Put on jewellery\n" "R : Remove jewellery\n", true, true, cmdhelp_textfilter); cols.add_formatted( 0, "In-game Toggles:\n" "Ctrl-A : toggle Autopickup\n" "Ctrl-V : toggle auto-prayer\n" " \n" " \n" " \n", true, true, cmdhelp_textfilter); cols.add_formatted( 0, level_map_help, true, true, cmdhelp_textfilter); cols.add_formatted( 0, "Item types (and common commands)\n" ") : hand weapons (wield)\n" "( : missiles (throw or fire)\n" "[ : armour (Wear and Take off)\n" "% : food and corpses (eat and Dissect)\n" "? : scrolls (read)\n" "! : potions (quaff)\n" "= : rings (Put on and Remove)\n" "\" : amulets (Put on and Remove)\n" "/ : wands (zap)\n" "+ : books (read, Memorise and Zap)\n" "\\ : staves and rods (wield and Evoke)\n" "} : miscellaneous items (Evoke)\n" "0 : the Orb of Zot\n" "\n" "$ : gold\n" " \n", true, true, cmdhelp_textfilter); cols.add_formatted( 0, "Stash Management Commands:\n" "Ctrl-F : Find (in stashes and shops)\n" "\n" "Searching in stashes allows regular\n" "expressions, and terms like 'altar'\n" "or 'artifact' or 'long blades'.\n", true, true, cmdhelp_textfilter); cols.add_formatted( 1, "Game Saving and Quitting:\n" "S : Save game and exit \n" "Q : Quit without saving\n" "Ctrl-X : save game without query\n", true, true, cmdhelp_textfilter, 45); cols.add_formatted( 1, "Player Character Information:\n" "@ : display character status\n" "[ : display worn armour\n" "( : display current weapons (also ))\n" "\" : display worn jewellery\n" "C : display experience info\n" "^ : show religion screen\n" "A : show Abilities/mutations\n" "\\ : show item knowledge\n" "m : show skill screen\n" "% : show resistances\n", true, true, cmdhelp_textfilter,45); cols.add_formatted( 1, "Dungeon Interaction and Information:\n" "o/c : Open/Close door\n" "<</> : use staircase (<< enter shop)\n" "; : examine occupied tile\n" "x : eXamine surroundings/targets\n" "X : eXamine level map\n" "O : show dungeon Overview\n", true, true, cmdhelp_textfilter,45); cols.add_formatted( 1, "Item Interaction (floor):\n" ", : pick up items (also g) \n" " (press twice for pick up menu) \n" "d : Drop an item\n" "d#: Drop exact number of items \n" "D : Dissect a corpse \n" "e : Eat food from floor \n", true, true, cmdhelp_textfilter); cols.add_formatted( 1, "Other Gameplay Actions:\n" "a : use special Ability\n" "p : Pray\n" "Z : cast a spell\n" "! : shout or command allies\n", true, true, cmdhelp_textfilter); cols.add_formatted( 1, "Non-Gameplay Commands / Info\n" "V : display Version information\n" "Ctrl-P : show Previous messages\n" "Ctrl-R : Redraw screen\n" "Ctrl-C : Clear main and level maps\n" "# : dump character to file\n" ": : add note to dump file\n" "_ : show notes\n" "~ : add macro\n" "= : reassign inventory/spell letters\n" " \n", true, true, cmdhelp_textfilter); cols.add_formatted( 1, targeting_help, true, true, cmdhelp_textfilter); cols.add_formatted( 1, "Shortcuts in Lists (like multidrop):\n" ") : selects hand weapons\n" "( : selects missiles\n" "[ : selects armour\n" "% : selects food, & : selects carrion\n" "? : selects scrolls\n" "! : selects potions\n" "= : selects rings\n" "\" : selects amulets\n" "/ : selects wands\n" "+ : selects books\n" "\\ : selects staves\n" "} : selects miscellaneous items\n" "Carry the Orb to the surface and win!\n" ", : global selection\n" "- : global deselection\n" "* : invert selection\n", true, true, cmdhelp_textfilter); cols.add_formatted( 1, " \n" "Crawl usually considers every item it\n" "sees as a stash. When using a value\n" "different from stash_tracking = all, you\n" "can use Ctrl-S to manually declare\n" "stashes, and Ctrl-E to erase them.\n", true, true, cmdhelp_textfilter); show_keyhelp_menu(cols.formatted_lines(), true); } void list_tutorial_help() { // 2 columns, split at column 40. column_composer cols(2, 41); // Page size is number of lines - one line for --more-- prompt. cols.set_pagesize(get_number_of_lines()); cols.add_formatted( 0, "Item types (and common commands)\n" ") : hand weapons (wield)\n" "( : missiles (throw or fire)\n" "[ : armour (Wear and Take off)\n" "% : food and corpses (eat and Dissect)\n" "? : scrolls (read)\n" "! : potions (quaff)\n" "= : rings (Put on and Remove)\n" "\" : amulets (Put on and Remove)\n" "/ : wands (zap)\n" // is it possible to replace that with e.g. Options.char_table[DNGN_ITEM_BOOK] "+, : : books (read, Memorise and Zap)\n" "\\, | : staves, rods (wield and Evoke)\n" "\n" "Movement and attacking\n" "Use the numpad for movement (try both\n" "Numlock on and off). You can also use\n" " hjkl : left, down, up, right and\n" " yubn : diagonal movement.\n" "Walking into a monster will attack it\n" "with the wielded weapon or barehanded.\n" "For ranged attacks use either\n" "f to launch missiles (like arrows)\n" "t to throw items by hand (like darts)\n" "Z to cast spells (Z? lists spells).\n", true, true, cmdhelp_textfilter); cols.add_formatted( 1, "Additional important commands\n" "S : Save the game and exit\n" "s : search for one turn (also . and Del)\n" "5 : rest full/search longer (Shift-Num 5)\n" "x : examine surroundings\n" "v : examine object in inventory\n" "i : list inventory\n" "g : pick up item from ground (also ,)\n" "d : drop item\n" "X : show map of the whole level\n" "<< or > : ascend/descend the stairs\n" "Ctrl-P : show previous messages\n" "\n" "Targeting (for spells and missiles)\n" "Use + (or =) and - to cycle between\n" "hostile monsters. Enter or . or Del\n" "all fire at the selected target.\n" "If the previous target is still alive\n" "and in sight, one of f, p, t fires\n" "at it again (without selecting anything).\n" "Any movement key fires straight away in\n" "the chosen direction.\n", true, true, cmdhelp_textfilter,40); show_keyhelp_menu(cols.formatted_lines(), false); } static void list_wizard_commands() { const char *line; int j = 0; clrscr(); // BCR - Set to screen length - 1 to display the "more" string int moreLength = (get_number_of_lines() - 1) * 2; for (int i = 0; i < 500; i++) { line = wizard_string( i ); if (strlen( line ) != 0) { // BCR - If we've reached the end of the screen, clear if (j == moreLength) { gotoxy(2, j / 2 + 1); cprintf("More..."); getch(); clrscr(); j = 0; } gotoxy( ((j % 2) ? 40 : 2), ((j / 2) + 1) ); cprintf( "%s", line ); j++; } } getch(); return; } // end list_commands() static const char *wizard_string( int i ) { UNUSED( i ); #ifdef WIZARD return((i == 10) ? "a : acquirement" : (i == 13) ? "A : set all skills to level" : (i == 15) ? "b : controlled blink" : (i == 20) ? "B : banish yourself to the Abyss" : (i == 30) ? "g : add a skill" : (i == 35) ? "G : remove all monsters" : (i == 40) ? "h/H : heal yourself (super-Heal)" : (i == 50) ? "i/I : identify/unidentify inventory": (i == 70) ? "l : make entrance to labyrinth" : (i == 80) ? "m/M : create monster by number/name": (i == 90) ? "o/% : create an object" : (i == 100) ? "p : make entrance to pandemonium" : (i == 110) ? "x : gain an experience level" : (i == 115) ? "r : change character's species" : (i == 120) ? "s : gain 20000 skill points" : (i == 130) ? "S : set skill to level" : (i == 140) ? "t : tweak object properties" : (i == 150) ? "X : Receive a gift from Xom" : (i == 160) ? "z/Z : cast any spell by number/name": (i == 200) ? "$ : get 1000 gold" : (i == 210) ? " : create up/down staircase" : (i == 220) ? "u/d : shift up/down one level" : (i == 230) ? "~/\" : goto a level" : (i == 240) ? "( : create a feature" : (i == 250) ? "] : get a mutation" : (i == 260) ? "[ : get a demonspawn mutation" : (i == 270) ? ": : find branch" : (i == 280) ? "{ : magic mapping" : (i == 290) ? "^ : gain piety" : (i == 300) ? "_ : gain religion" : (i == 310) ? "\' : list items" : (i == 320) ? "? : list wizard commands" : (i == 330) ? "| : acquire all unrand artefacts" : (i == 340) ? "+ : turn item into random artefact" : (i == 350) ? "= : sum skill points" : ""); #else return (""); #endif } // end wizard_string()