summaryrefslogtreecommitdiffstats
path: root/stone_soup/crawl-ref/source/debug.cc
diff options
context:
space:
mode:
Diffstat (limited to 'stone_soup/crawl-ref/source/debug.cc')
-rw-r--r--stone_soup/crawl-ref/source/debug.cc2136
1 files changed, 0 insertions, 2136 deletions
diff --git a/stone_soup/crawl-ref/source/debug.cc b/stone_soup/crawl-ref/source/debug.cc
deleted file mode 100644
index eb29e8c9d9..0000000000
--- a/stone_soup/crawl-ref/source/debug.cc
+++ /dev/null
@@ -1,2136 +0,0 @@
-/*
- * File: debug.cc
- * Summary: Debug and wizard related functions.
- * Written by: Linley Henzell and Jesse Jones
- *
- * Change History (most recent first):
- *
- * <4> 14/12/99 LRH Added cast_spec_spell_name()
- * <3> 5/06/99 JDJ Added TRACE.
- * <2> -/--/-- JDJ Added a bunch od debugging macros.
- * Old code is now #if WIZARD.
- * <1> -/--/-- LRH Created
- */
-
-#include "AppHdr.h"
-#include "debug.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <time.h>
-#include <ctype.h>
-
-#ifdef DOS
-#include <conio.h>
-#endif
-
-#include "externs.h"
-
-#include "direct.h"
-#include "dungeon.h"
-#include "fight.h"
-#include "invent.h"
-#include "itemname.h"
-#include "itemprop.h"
-#include "item_use.h"
-#include "items.h"
-#include "misc.h"
-#include "monplace.h"
-#include "monstuff.h"
-#include "mon-util.h"
-#include "mutation.h"
-#include "player.h"
-#include "randart.h"
-#include "religion.h"
-#include "skills.h"
-#include "skills2.h"
-#include "spl-cast.h"
-#include "spl-util.h"
-#include "stuff.h"
-#include "version.h"
-
-#ifndef WIZARD
-#define WIZARD
-#endif
-
-#if DEBUG && WIN
-#define MyDebugBreak() _asm {int 3}
-#endif
-
-//-----------------------------------
-// Internal Variables
-//
-#if WIN
-static HANDLE sConsole = NULL;
-#endif
-
-// ========================================================================
-// Internal Functions
-// ========================================================================
-
-//---------------------------------------------------------------
-//
-// BreakStrToDebugger
-//
-//---------------------------------------------------------------
-#if DEBUG
-static void BreakStrToDebugger(const char *mesg)
-{
-
-#if OSX
- fprintf(stderr, mesg);
-// raise(SIGINT); // this is what DebugStr() does on OS X according to Tech Note 2030
- int* p = NULL; // but this gives us a stack crawl...
- *p = 0;
-#elif MAC
- unsigned char s[50];
-
- int len = strlen(mesg);
-
- if (len > 255)
- len = 255;
-
- s[0] = (Byte) len;
- BlockMoveData(mesg, s + 1, len);
-
- DebugStr(s);
-
-#elif WIN
- MSG msg; // remove pending quit messages so the message box displays
-
- bool quitting = (bool)::PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE);
-
- char text[2500];
-
- int flags = MB_YESNO + // want abort and ignore buttons
- // (too bad we can't ditch the retry button...)
- MB_ICONERROR + // display the icon for errors
- MB_TASKMODAL + // don't let the user do anything else in the app
- MB_SETFOREGROUND; // bring the app to the front
-
- strcpy(text, mesg);
- strcat(text, "\nDo you want to drop into the debugger?");
-
- int result = MessageBoxA(NULL, text, "Debug Break", flags);
-
- if (result == IDYES)
- MyDebugBreak();
-
- if (quitting)
- PostQuitMessage(msg.wParam);
-
-#else
- fprintf(stderr, "%s\n", mesg);
- abort();
-#endif
-}
-#endif
-
-
-//---------------------------------------------------------------
-//
-// IsDebuggerPresent95
-//
-// From March 1999 Windows Developer's Journal. This should only
-// be called if we're running on Win 95 (normally I'd add an
-// ASSERT, but that's a bit dicy since this is called by ASSERT...)
-//
-//---------------------------------------------------------------
-#if WIN
-static bool IsDebuggerPresent95()
-{
- bool present = false;
-
- const DWORD kDebuggerPresentFlag = 0x000000001;
- const DWORD kProcessDatabaseBytes = 190;
- const DWORD kOffsetFlags = 8;
-
- DWORD threadID = GetCurrentThreadId();
- DWORD processID = GetCurrentProcessId();
- DWORD obfuscator = 0;
-
-#if __MWERKS__
- asm
- {
- mov ax, fs
- mov es, ax
- mov eax, 0x18
- mov eax, es:[eax]
- sub eax, 0x10 xor eax,[threadID] mov[obfuscator], eax
- }
-
-#else
- _asm
- {
- mov ax, fs
- mov es, ax
- mov eax, 18 h
- mov eax, es:[eax]
- sub eax, 10 h xor eax,[threadID] mov[obfuscator], eax
- }
-#endif
-
- const DWORD *processDatabase =
- reinterpret_cast< const DWORD * >(processID ^ obfuscator);
-
- if (!IsBadReadPtr(processDatabase, kProcessDatabaseBytes))
- {
- DWORD flags = processDatabase[kOffsetFlags];
-
- present = (flags & kDebuggerPresentFlag) != 0;
- }
-
- return present;
-}
-#endif
-
-
-//---------------------------------------------------------------
-//
-// IsDebuggerPresent
-//
-//---------------------------------------------------------------
-#if WIN
-bool IsDebuggerPresent()
-{
- bool present = false;
-
- typedef BOOL(WINAPI * IsDebuggerPresentProc) ();
-
- HINSTANCE kernelH = LoadLibrary("KERNEL32.DLL");
-
- if (kernelH != NULL)
- { // should never fail
-
- IsDebuggerPresentProc proc =
- (IsDebuggerPresentProc)::GetProcAddress( kernelH,
- "IsDebuggerPresent" );
-
- if (proc != NULL) // only present in NT and Win 98
- present = proc() != 0;
- else
- present = IsDebuggerPresent95();
- }
-
- return present;
-}
-#endif
-
-
-//---------------------------------------------------------------
-//
-// CreateConsoleWindow
-//
-//---------------------------------------------------------------
-#if WIN
-static void CreateConsoleWindow()
-{
- ASSERT(sConsole == NULL);
-
- // Create the console window
- if (::AllocConsole())
- {
- // Get the console window's handle
- sConsole =::GetStdHandle(STD_ERROR_HANDLE);
- if (sConsole == INVALID_HANDLE_VALUE)
- sConsole = NULL;
-
- // Set some options
- if (sConsole != NULL)
- {
- VERIFY(::SetConsoleTextAttribute(sConsole, FOREGROUND_GREEN));
- // green text on a black background (there doesn't appear to
- // be a way to get black text)
-
- VERIFY(::SetConsoleTitle("Debug Log"));
-
- COORD size = { 80, 120 };
-
- VERIFY(::SetConsoleScreenBufferSize(sConsole, size));
- }
- else
- DEBUGSTR(L "Couldn't get the console window's handle!");
- }
- else
- DEBUGSTR(L "Couldn't allocate the console window!");
-}
-#endif
-
-
-#if DEBUG
-//---------------------------------------------------------------
-//
-// TraceString
-//
-//---------------------------------------------------------------
-static void TraceString(const char *mesg)
-{
- // Write the string to the debug window
-#if WIN
- if (IsDebuggerPresent())
- {
- OutputDebugStringA(mesg); // if you're using CodeWarrior you'll need to enable the "Log System Messages" checkbox to get this working
- }
- else
- {
- if (sConsole == NULL) // otherwise we'll use a console window
- CreateConsoleWindow();
-
- if (sConsole != NULL)
- {
- unsigned long written;
-
- VERIFY(WriteConsoleA(sConsole, mesg, strlen(mesg), &written, NULL));
- }
- }
-#else
- fprintf(stderr, "%s", mesg);
-#endif
-
- // Write the string to the debug log
- static bool inited = false;
- static FILE *file = NULL;
-
- if (!inited)
- {
- ASSERT(file == NULL);
-
- const char *fileName = "DebugLog.txt";
-
- file = fopen(fileName, "w");
- ASSERT(file != NULL);
-
- inited = true;
- }
-
- if (file != NULL)
- {
- fputs(mesg, file);
- fflush(file); // make sure all the output makes it to the file
-
- }
-}
-#endif
-
-#if MAC
-#pragma mark -
-#endif
-
-// ========================================================================
-// Global Functions
-// ========================================================================
-
-//---------------------------------------------------------------
-//
-// AssertFailed
-//
-//---------------------------------------------------------------
-#if DEBUG
-void AssertFailed(const char *expr, const char *file, int line)
-{
- char mesg[512];
-
-#if MAC
- sprintf(mesg, "ASSERT(%s) in %s at line %d failed.", expr, file, line);
-
-#else
- const char *fileName = file + strlen(file); // strip off path
-
- while (fileName > file && fileName[-1] != '\\')
- --fileName;
-
- sprintf(mesg, "ASSERT(%s) in '%s' at line %d failed.", expr, fileName,
- line);
-#endif
-
- BreakStrToDebugger(mesg);
-}
-#endif
-
-
-//---------------------------------------------------------------
-//
-// DEBUGSTR
-//
-//---------------------------------------------------------------
-#if DEBUG
-void DEBUGSTR(const char *format, ...)
-{
- char mesg[2048];
-
- va_list args;
-
- va_start(args, format);
- vsprintf(mesg, format, args);
- va_end(args);
-
- BreakStrToDebugger(mesg);
-}
-#endif
-
-
-//---------------------------------------------------------------
-//
-// TRACE
-//
-//---------------------------------------------------------------
-#if DEBUG
-void TRACE(const char *format, ...)
-{
- char mesg[2048];
-
- va_list args;
-
- va_start(args, format);
- vsprintf(mesg, format, args);
- va_end(args);
-
- TraceString(mesg);
-}
-#endif // DEBUG
-
-//---------------------------------------------------------------
-//
-// debug_prompt_for_monster
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-
-static int get_monnum(const char *name)
-{
- char search[ITEMNAME_SIZE],
- mname[ITEMNAME_SIZE];
- strncpy(search, name, sizeof search);
- search[ITEMNAME_SIZE - 1] = 0;
- strlwr(search);
-
- int mon = -1;
- for (int i = 0; i < NUM_MONSTERS; i++)
- {
- moname( i, true, DESC_PLAIN, mname );
-
- const char *ptr = strstr( strlwr(mname), search );
- if (ptr != NULL)
- {
- if (ptr == mname)
- {
- // we prefer prefixes over partial matches
- mon = i;
- break;
- }
- else
- mon = i;
- }
- }
- return (mon);
-}
-
-static int debug_prompt_for_monster( void )
-{
- char specs[80];
-
- mpr( "(Hint: 'generated' names, eg 'orc zombie', won't work)", MSGCH_PROMPT );
- mpr( "Which monster by name? ", MSGCH_PROMPT );
- get_input_line( specs, sizeof( specs ) );
-
- if (specs[0] == '\0')
- return (-1);
-
- return (get_monnum(specs));
-}
-#endif
-
-//---------------------------------------------------------------
-//
-// debug_prompt_for_skill
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-static int debug_prompt_for_skill( const char *prompt )
-{
- char specs[80];
-
- mpr( prompt, MSGCH_PROMPT );
- get_input_line( specs, sizeof( specs ) );
-
- if (specs[0] == '\0')
- return (-1);
-
- int skill = -1;
-
- for (int i = 0; i < NUM_SKILLS; i++)
- {
- // avoid the bad values:
- if (i == SK_UNUSED_1 || (i > SK_UNARMED_COMBAT && i < SK_SPELLCASTING))
- continue;
-
- char sk_name[80];
- strncpy( sk_name, skill_name(i), sizeof( sk_name ) );
-
- char *ptr = strstr( strlwr(sk_name), strlwr(specs) );
- if (ptr != NULL)
- {
- if (ptr == sk_name && strlen(specs) > 0)
- {
- // we prefer prefixes over partial matches
- skill = i;
- break;
- }
- else
- skill = i;
- }
- }
-
- return (skill);
-}
-#endif
-
-//---------------------------------------------------------------
-//
-// debug_change_species
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-void debug_change_species( void )
-{
- char specs[80];
- int i;
-
- mpr( "What species would you like to be now? " , MSGCH_PROMPT );
- get_input_line( specs, sizeof( specs ) );
-
- if (specs[0] == '\0')
- return;
-
- int sp = -1;
-
- for (int i = SP_HUMAN; i < NUM_SPECIES; i++)
- {
- char sp_name[80];
- strncpy( sp_name, species_name(i, you.experience_level), sizeof( sp_name ) );
-
- char *ptr = strstr( strlwr(sp_name), strlwr(specs) );
- if (ptr != NULL)
- {
- if (ptr == sp_name && strlen(specs) > 0)
- {
- // we prefer prefixes over partial matches
- sp = i;
- break;
- }
- else
- sp = i;
- }
- }
-
- if (sp == -1)
- mpr( "That species isn't available." );
- else
- {
- for (i = 0; i < NUM_SKILLS; i++)
- {
- you.skill_points[i] *= species_skills( i, sp );
- you.skill_points[i] /= species_skills( i, you.species );
- }
-
- you.species = sp;
-
- redraw_screen();
- }
-}
-#endif
-//---------------------------------------------------------------
-//
-// debug_prompt_for_int
-//
-// If nonneg, then it returns a non-negative number or -1 on fail
-// If !nonneg, then it returns an integer, and 0 on fail
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-static int debug_prompt_for_int( const char *prompt, bool nonneg )
-{
- char specs[80];
-
- mpr( prompt, MSGCH_PROMPT );
- get_input_line( specs, sizeof( specs ) );
-
- if (specs[0] == '\0')
- return (nonneg ? -1 : 0);
-
- char *end;
- int ret = strtol( specs, &end, 10 );
-
- if ((ret < 0 && nonneg) || (ret == 0 && end == specs))
- ret = (nonneg ? -1 : 0);
-
- return (ret);
-}
-#endif
-
-/*
- Some debugging functions, accessable through keys like %, $, &, ) etc when
- a section of code in input() in acr.cc is uncommented.
- */
-
-//---------------------------------------------------------------
-//
-// cast_spec_spell
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-void cast_spec_spell(void)
-{
- int spell = debug_prompt_for_int( "Cast which spell by number? ", true );
-
- if (spell == -1)
- canned_msg( MSG_OK );
- else
- your_spells( spell, 0, false );
-}
-#endif
-
-
-//---------------------------------------------------------------
-//
-// cast_spec_spell_name
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-void cast_spec_spell_name(void)
-{
- int i = 0;
- char specs[80];
- char spname[80];
-
- mpr( "Cast which spell by name? ", MSGCH_PROMPT );
- get_input_line( specs, sizeof( specs ) );
-
- for (i = 0; i < NUM_SPELLS; i++)
- {
- strncpy( spname, spell_title(i), sizeof( spname ) );
-
- if (strstr( strlwr(spname), strlwr(specs) ) != NULL)
- {
- your_spells(i, 0, false);
- return;
- }
- }
-
- mpr((one_chance_in(20)) ? "Maybe you should go back to WIZARD school."
- : "I couldn't find that spell.");
-}
-#endif
-
-
-//---------------------------------------------------------------
-//
-// create_spec_monster
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-void create_spec_monster(void)
-{
- int mon = debug_prompt_for_int( "Create which monster by number? ", true );
-
- if (mon == -1)
- canned_msg( MSG_OK );
- else
- create_monster( mon, 0, BEH_SLEEP, you.x_pos, you.y_pos, MHITNOT, 250 );
-} // end create_spec_monster()
-#endif
-
-
-//---------------------------------------------------------------
-//
-// create_spec_monster_name
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-void create_spec_monster_name(void)
-{
- int mon = debug_prompt_for_monster();
-
- if (mon == -1)
- {
- mpr("I couldn't find that monster.");
-
- if (one_chance_in(20))
- mpr("Maybe it's hiding.");
- }
- else
- {
- create_monster(mon, 0, BEH_SLEEP, you.x_pos, you.y_pos, MHITNOT, 250);
- }
-} // end create_spec_monster_name()
-#endif
-
-
-//---------------------------------------------------------------
-//
-// level_travel
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-void level_travel( int delta )
-{
- int old_level = you.your_level;
- int new_level = you.your_level + delta;
-
- if (delta == 0)
- {
- new_level = debug_prompt_for_int( "Travel to which level? ", true ) - 1;
- }
-
- if (new_level < 0 || new_level >= 50)
- {
- mpr( "That level is out of bounds." );
- return;
- }
-
- you.your_level = new_level - 1;
- grd[you.x_pos][you.y_pos] = DNGN_STONE_STAIRS_DOWN_I;
- down_stairs(true, old_level);
- untag_followers();
-} // end level_travel()
-#endif
-
-
-//---------------------------------------------------------------
-//
-// create_spec_object
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-void create_spec_object(void)
-{
- static int max_subtype[] =
- {
- NUM_WEAPONS,
- NUM_MISSILES,
- NUM_ARMOURS,
- NUM_WANDS,
- NUM_FOODS,
- 0, // unknown I
- NUM_SCROLLS,
- NUM_JEWELLERY,
- NUM_POTIONS,
- 0, // unknown II
- NUM_BOOKS,
- NUM_STAVES,
- 0, // Orbs -- only one, handled specially
- NUM_MISCELLANY,
- 0, // corpses -- handled specially
- 0, // gold -- handled specially
- 0, // "gemstones" -- no items of type
- };
-
- char specs[80];
- char obj_name[ ITEMNAME_SIZE ];
- char keyin;
-
- char * ptr;
- int best_index;
- int mon;
- int i;
-
- int class_wanted = OBJ_UNASSIGNED;
- int type_wanted = -1;
- int special_wanted = 0;
-
- int thing_created;
-
- for (;;)
- {
- mpr(") - weapons ( - missiles [ - armour / - wands ? - scrolls",
- MSGCH_PROMPT);
- mpr("= - jewellery ! - potions : - books | - staves 0 - The Orb",
- MSGCH_PROMPT);
- mpr("} - miscellany X - corpses %% - food $ - gold ESC - exit",
- MSGCH_PROMPT);
-
- mpr("What class of item? ", MSGCH_PROMPT);
-
- keyin = toupper( get_ch() );
-
- if (keyin == ')')
- class_wanted = OBJ_WEAPONS;
- else if (keyin == '(')
- class_wanted = OBJ_MISSILES;
- else if (keyin == '[' || keyin == ']')
- class_wanted = OBJ_ARMOUR;
- else if (keyin == '/' || keyin == '\\')
- class_wanted = OBJ_WANDS;
- else if (keyin == '?')
- class_wanted = OBJ_SCROLLS;
- else if (keyin == '=' || keyin == '"')
- class_wanted = OBJ_JEWELLERY;
- else if (keyin == '!')
- class_wanted = OBJ_POTIONS;
- else if (keyin == ':')
- class_wanted = OBJ_BOOKS;
- else if (keyin == '|')
- class_wanted = OBJ_STAVES;
- else if (keyin == '0' || keyin == 'O')
- class_wanted = OBJ_ORBS;
- else if (keyin == '}' || keyin == '{')
- class_wanted = OBJ_MISCELLANY;
- else if (keyin == 'X')
- class_wanted = OBJ_CORPSES;
- else if (keyin == '%')
- class_wanted = OBJ_FOOD;
- else if (keyin == '$')
- class_wanted = OBJ_GOLD;
- else if (keyin == ESCAPE || keyin == ' '
- || keyin == '\r' || keyin == '\n')
- {
- canned_msg( MSG_OK );
- return;
- }
-
- if (class_wanted != OBJ_UNASSIGNED)
- break;
- }
-
- // allocate an item to play with:
- thing_created = get_item_slot();
- if (thing_created == NON_ITEM)
- {
- mpr( "Could not allocate item." );
- return;
- }
-
- // turn item into appropriate kind:
- if (class_wanted == OBJ_ORBS)
- {
- mitm[thing_created].base_type = OBJ_ORBS;
- mitm[thing_created].sub_type = ORB_ZOT;
- mitm[thing_created].quantity = 1;
- }
- else if (class_wanted == OBJ_GOLD)
- {
- int amount = debug_prompt_for_int( "How much gold? ", true );
- if (amount <= 0)
- {
- canned_msg( MSG_OK );
- return;
- }
-
- mitm[thing_created].base_type = OBJ_GOLD;
- mitm[thing_created].sub_type = 0;
- mitm[thing_created].quantity = amount;
- }
- else if (class_wanted == OBJ_CORPSES)
- {
- mon = debug_prompt_for_monster();
-
- if (mon == -1)
- {
- mpr( "No such monster." );
- return;
- }
-
- mitm[thing_created].base_type = OBJ_CORPSES;
- mitm[thing_created].sub_type = CORPSE_BODY;
- mitm[thing_created].plus = mon;
- mitm[thing_created].plus2 = 0;
- mitm[thing_created].special = 210;
- mitm[thing_created].colour = mons_colour(mon);;
- mitm[thing_created].quantity = 1;
- mitm[thing_created].flags = 0;
- }
- else
- {
- mpr( "What type of item? ", MSGCH_PROMPT );
- get_input_line( specs, sizeof( specs ) );
-
- if (specs[0] == '\0')
- {
- canned_msg( MSG_OK );
- return;
- }
-
- // In order to get the sub-type, we'll fill out the base type...
- // then we're going to iterate over all possible subtype values
- // and see if we get a winner. -- bwr
- mitm[thing_created].base_type = class_wanted;
- mitm[thing_created].sub_type = 0;
- mitm[thing_created].plus = 0;
- mitm[thing_created].plus2 = 0;
- mitm[thing_created].special = 0;
- mitm[thing_created].flags = 0;
- mitm[thing_created].quantity = 1;
- set_ident_flags( mitm[thing_created], ISFLAG_IDENT_MASK );
-
- if (class_wanted == OBJ_ARMOUR)
- {
- if (strstr( "naga barding", specs ))
- {
- mitm[thing_created].sub_type = ARM_NAGA_BARDING;
- }
- else if (strstr( "centaur barding", specs ))
- {
- mitm[thing_created].sub_type = ARM_CENTAUR_BARDING;
- }
- else if (strstr( "wizard's hat", specs ))
- {
- mitm[thing_created].sub_type = ARM_HELMET;
- mitm[thing_created].plus2 = THELM_WIZARD_HAT;
- }
- else if (strstr( "cap", specs ))
- {
- mitm[thing_created].sub_type = ARM_HELMET;
- mitm[thing_created].plus2 = THELM_CAP;
- }
- else if (strstr( "helm", specs ))
- {
- mitm[thing_created].sub_type = ARM_HELMET;
- mitm[thing_created].plus2 = THELM_HELM;
- }
- }
-
- if (!mitm[thing_created].sub_type)
- {
- type_wanted = -1;
- best_index = 10000;
-
- for (i = 0; i < max_subtype[ mitm[thing_created].base_type ]; i++)
- {
- mitm[thing_created].sub_type = i;
- item_name( mitm[thing_created], DESC_PLAIN, obj_name );
-
- ptr = strstr( strlwr(obj_name), strlwr(specs) );
- if (ptr != NULL)
- {
- // earliest match is the winner
- if (ptr - obj_name < best_index)
- {
- mpr( obj_name );
- type_wanted = i;
- best_index = ptr - obj_name;
- }
- }
- }
-
- if (type_wanted == -1)
- {
- // ds -- if specs is a valid int, try using that.
- // Since zero is atoi's copout, the wizard
- // must enter (subtype + 1).
- if (!(type_wanted = atoi(specs)))
- {
- mpr( "No such item." );
- return;
- }
- type_wanted--;
- }
-
- mitm[thing_created].sub_type = type_wanted;
- }
-
- switch (mitm[thing_created].base_type)
- {
- case OBJ_MISSILES:
- mitm[thing_created].quantity = 30;
- // intentional fall-through
- case OBJ_WEAPONS:
- case OBJ_ARMOUR:
- mpr( "What ego type? ", MSGCH_PROMPT );
- get_input_line( specs, sizeof( specs ) );
-
- if (specs[0] != '\0')
- {
- special_wanted = 0;
- best_index = 10000;
-
- for (i = 1; i < 25; i++)
- {
- mitm[thing_created].special = i;
- item_name( mitm[thing_created], DESC_PLAIN, obj_name );
-
- ptr = strstr( strlwr(obj_name), strlwr(specs) );
- if (ptr != NULL)
- {
- // earliest match is the winner
- if (ptr - obj_name < best_index)
- {
- mpr( obj_name );
- special_wanted = i;
- best_index = ptr - obj_name;
- }
- }
- }
-
- mitm[thing_created].special = special_wanted;
- }
- break;
-
- case OBJ_BOOKS:
- if (mitm[thing_created].sub_type == BOOK_MANUAL)
- {
- special_wanted = debug_prompt_for_skill( "A manual for which skill? " );
- if (special_wanted != -1)
- mitm[thing_created].plus = special_wanted;
- else
- mpr( "Sorry, no books on that skill today." );
- }
- break;
-
- case OBJ_WANDS:
- mitm[thing_created].plus = 24;
- break;
-
- case OBJ_STAVES:
- if (item_is_rod( mitm[thing_created] ))
- {
- mitm[thing_created].plus = MAX_ROD_CHARGE * ROD_CHARGE_MULT;
- mitm[thing_created].plus2 = MAX_ROD_CHARGE * ROD_CHARGE_MULT;
- }
- break;
-
- case OBJ_MISCELLANY:
- // Runes to "demonic", decks have 50 cards, ignored elsewhere?
- mitm[thing_created].plus = 50;
- break;
-
- case OBJ_FOOD:
- case OBJ_SCROLLS:
- case OBJ_POTIONS:
- mitm[thing_created].quantity = 12;
- break;
-
- default:
- break;
- }
- }
-
- item_colour( mitm[thing_created] );
-
- move_item_to_grid( &thing_created, you.x_pos, you.y_pos );
-
- if (thing_created != NON_ITEM)
- {
- origin_acquired( mitm[thing_created], AQ_WIZMODE );
- canned_msg( MSG_SOMETHING_APPEARS );
- }
-}
-#endif
-
-
-//---------------------------------------------------------------
-//
-// create_spec_object
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-void tweak_object(void)
-{
- char specs[50];
- char keyin;
-
- int item = prompt_invent_item( "Tweak which item? ", -1 );
- if (item == PROMPT_ABORT)
- {
- canned_msg( MSG_OK );
- return;
- }
-
- if (item == you.equip[EQ_WEAPON])
- you.wield_change = true;
-
- for (;;)
- {
- void *field_ptr = NULL;
-
- for (;;)
- {
- item_name( you.inv[item], DESC_INVENTORY_EQUIP, info );
- mpr( info );
-
- mpr( "a - plus b - plus2 c - special d - quantity ESC - exit",
- MSGCH_PROMPT );
- mpr( "Which field? ", MSGCH_PROMPT );
-
- keyin = tolower( get_ch() );
-
- if (keyin == 'a')
- field_ptr = &(you.inv[item].plus);
- else if (keyin == 'b')
- field_ptr = &(you.inv[item].plus2);
- else if (keyin == 'c')
- field_ptr = &(you.inv[item].special);
- else if (keyin == 'd')
- field_ptr = &(you.inv[item].quantity);
- else if (keyin == ESCAPE || keyin == ' '
- || keyin == '\r' || keyin == '\n')
- {
- canned_msg( MSG_OK );
- return;
- }
-
- if (keyin >= 'a' && keyin <= 'd')
- break;
- }
-
- if (keyin != 'c')
- {
- const short *const ptr = static_cast< short * >( field_ptr );
- snprintf( info, INFO_SIZE, "Old value: %d (0x%04x)", *ptr, *ptr );
- }
- else
- {
- const long *const ptr = static_cast< long * >( field_ptr );
- snprintf( info, INFO_SIZE, "Old value: %ld (0x%08lx)", *ptr, *ptr );
- }
-
- mpr( info );
-
- mpr( "New value? ", MSGCH_PROMPT );
- get_input_line( specs, sizeof( specs ) );
-
- if (specs[0] == '\0')
- return;
-
- char *end;
- int new_value = strtol( specs, &end, 10 );
-
- if (new_value == 0 && end == specs)
- return;
-
- if (keyin != 'c')
- {
- short *ptr = static_cast< short * >( field_ptr );
- *ptr = new_value;
- }
- else
- {
- long *ptr = static_cast< long * >( field_ptr );
- *ptr = new_value;
- }
- }
-}
-#endif
-
-
-//---------------------------------------------------------------
-//
-// stethoscope
-//
-//---------------------------------------------------------------
-#if DEBUG_DIAGNOSTICS
-
-static const char *enchant_names[] =
-{
- "None",
- "Slow", "Haste", "*BUG-3*", "Fear", "Conf", "Invis",
- "YPois-1", "YPois-2", "YPois-3", "YPois-4",
- "YShug-1", "YShug-2", "YShug-3", "YShug-4",
- "YRot-1", "YRot-2", "YRot-3", "YRot-4",
- "Summon", "Abj-1", "Abj-2", "Abj-3", "Abj-4", "Abj-5", "Abj-6",
- "Corona-1", "Corona-2", "Corona-3", "Corona-4",
- "Charm", "YSticky-1", "YSticky-2", "YSticky-3", "YSticky-4",
- "*BUG-35*", "*BUG-36*", "*BUG-37*",
- "GlowShapeshifter", "Shapeshifter",
- "Tele-1", "Tele-2", "Tele-3", "Tele-4",
- "*BUG-44*", "*BUG-45*", "*BUG-46*", "*BUG-47*", "*BUG-48*", "*BUG-49*",
- "*BUG-50*", "*BUG-51*", "*BUG-52*", "*BUG-53*", "*BUG-54*", "*BUG-55*",
- "*BUG-56*",
- "Pois-1", "Pois-2", "Pois-3", "Pois-4",
- "Sticky-1", "Sticky-2", "Sticky-3", "Sticky-4",
- "OldAbj-1", "OldAbj-2", "OldAbj-3", "OldAbj-4", "OldAbj-5", "OldAbj-6",
- "OldCreatedFriendly", "SleepWary", "Submerged", "Short Lived",
- "*BUG-too big*"
-};
-
-void stethoscope(int mwh)
-{
- struct dist stth;
- int steth_x, steth_y;
- int i, j;
-
- if (mwh != RANDOM_MONSTER)
- i = mwh;
- else
- {
- mpr( "Which monster?", MSGCH_PROMPT );
-
- direction( stth );
-
- if (!stth.isValid)
- return;
-
- if (stth.isTarget)
- {
- steth_x = stth.tx;
- steth_y = stth.ty;
- }
- else
- {
- steth_x = you.x_pos + stth.dx;
- steth_y = you.x_pos + stth.dy;
- }
-
- if (env.cgrid[steth_x][steth_y] != EMPTY_CLOUD)
- {
- snprintf( info, INFO_SIZE, "cloud type: %d delay: %d",
- env.cloud[ env.cgrid[steth_x][steth_y] ].type,
- env.cloud[ env.cgrid[steth_x][steth_y] ].decay );
-
- mpr( info, MSGCH_DIAGNOSTICS );
- }
-
- if (mgrd[steth_x][steth_y] == NON_MONSTER)
- {
- snprintf( info, INFO_SIZE, "item grid = %d", igrd[steth_x][steth_y] );
- mpr( info, MSGCH_DIAGNOSTICS );
- return;
- }
-
- i = mgrd[steth_x][steth_y];
- }
-
- // print type of monster
- snprintf( info, INFO_SIZE, "%s (id #%d; type=%d loc=(%d,%d) align=%s)",
- monam( menv[i].number, menv[i].type, true, DESC_CAP_THE ),
- i, menv[i].type,
- menv[i].x, menv[i].y,
- ((menv[i].attitude == ATT_FRIENDLY) ? "friendly" :
- (menv[i].attitude == ATT_HOSTILE) ? "hostile" :
- (menv[i].attitude == ATT_NEUTRAL) ? "neutral"
- : "unknown alignment") );
-
- mpr( info, MSGCH_DIAGNOSTICS );
-
- // print stats and other info
- snprintf( info, INFO_SIZE,"HD=%d HP=%d/%d AC=%d EV=%d MR=%d SP=%d energy=%d num=%d flags=%02x",
- menv[i].hit_dice,
- menv[i].hit_points, menv[i].max_hit_points,
- menv[i].armour_class, menv[i].evasion,
- mons_resist_magic( &menv[i] ),
- menv[i].speed, menv[i].speed_increment,
- menv[i].number, menv[i].flags );
-
- mpr( info, MSGCH_DIAGNOSTICS );
-
- // print behaviour information
-
- const int hab = monster_habitat( menv[i].type );
-
- snprintf( info, INFO_SIZE, "hab=%s beh=%s(%d) foe=%s(%d) mem=%d target=(%d,%d)",
- ((hab == DNGN_DEEP_WATER) ? "water" :
- (hab == DNGN_LAVA) ? "lava"
- : "floor"),
-
- ((menv[i].behaviour == BEH_SLEEP) ? "sleep" :
- (menv[i].behaviour == BEH_WANDER) ? "wander" :
- (menv[i].behaviour == BEH_SEEK) ? "seek" :
- (menv[i].behaviour == BEH_FLEE) ? "flee" :
- (menv[i].behaviour == BEH_CORNERED) ? "cornered"
- : "unknown"),
- menv[i].behaviour,
-
- ((menv[i].foe == MHITYOU) ? "you" :
- (menv[i].foe == MHITNOT) ? "none" :
- (menv[menv[i].foe].type == -1) ? "unassigned monster"
- : monam( menv[menv[i].foe].number, menv[menv[i].foe].type,
- true, DESC_PLAIN )),
- menv[i].foe,
- menv[i].foe_memory,
-
- menv[i].target_x, menv[i].target_y );
-
- mpr( info, MSGCH_DIAGNOSTICS );
-
- // print resistances
- snprintf( info, INFO_SIZE, "resist: fire=%d cold=%d elec=%d pois=%d neg=%d",
- mons_res_fire( &menv[i] ),
- mons_res_cold( &menv[i] ),
- mons_res_elec( &menv[i] ),
- mons_res_poison( &menv[i] ),
- mons_res_negative_energy( &menv[i] ) );
-
- mpr( info, MSGCH_DIAGNOSTICS );
-
-
- // print enchantments
- strncpy( info, "ench: ", INFO_SIZE );
- for (j = 0; j < 6; j++)
- {
- if (menv[i].enchantment[j] >= NUM_ENCHANTMENTS)
- strncat( info, enchant_names[ NUM_ENCHANTMENTS ], INFO_SIZE );
- else
- strncat( info, enchant_names[ menv[i].enchantment[j] ], INFO_SIZE );
-
- if (strlen( info ) <= 70)
- strncat( info, " ", INFO_SIZE );
- else if (j < 5)
- {
- mpr( info, MSGCH_DIAGNOSTICS );
- strncpy( info, "ench: ", INFO_SIZE );
- }
- }
-
- mpr( info, MSGCH_DIAGNOSTICS );
-
- if (menv[i].type == MONS_PLAYER_GHOST
- || menv[i].type == MONS_PANDEMONIUM_DEMON)
- {
- snprintf( info, INFO_SIZE, "Ghost damage: %d; brand: %d",
- ghost.values[ GVAL_DAMAGE ], ghost.values[ GVAL_BRAND ] );
- mpr( info, MSGCH_DIAGNOSTICS );
- }
-} // end stethoscope()
-#endif
-
-#if DEBUG_ITEM_SCAN
-//---------------------------------------------------------------
-//
-// dump_item
-//
-//---------------------------------------------------------------
-static void dump_item( const char *name, int num, const item_def &item )
-{
- mpr( name, MSGCH_WARN );
-
- snprintf( info, INFO_SIZE, " item #%d: base: %d; sub: %d; plus: %d; plus2: %d; special: %ld",
- num, item.base_type, item.sub_type,
- item.plus, item.plus2, item.special );
-
- mpr( info );
-
- snprintf( info, INFO_SIZE, " quant: %d; colour: %d; ident: 0x%08lx; ident_type: %d",
- item.quantity, item.colour, item.flags,
- get_ident_type( item.base_type, item.sub_type ) );
-
- mpr( info );
-
- snprintf( info, INFO_SIZE, " x: %d; y: %d; link: %d",
- item.x, item.y, item.link );
-
- mpr( info );
-}
-
-//---------------------------------------------------------------
-//
-// debug_item_scan
-//
-//---------------------------------------------------------------
-void debug_item_scan( void )
-{
- int i;
- char name[256];
-
- // unset marks
- for (i = 0; i < MAX_ITEMS; i++)
- mitm[i].flags &= (~ISFLAG_DEBUG_MARK);
-
- // First we're going to check all the stacks on the level:
- for (int x = 0; x < GXM; x++)
- {
- for (int y = 0; y < GYM; y++)
- {
- // These are unlinked monster inventory items -- skip them:
- if (x == 0 && y == 0)
- continue;
-
- // Looking for infinite stacks (ie more links than tems allowed)
- // and for items which have bad coordinates (can't find their stack)
- for (int obj = igrd[x][y]; obj != NON_ITEM; obj = mitm[obj].link)
- {
- // Check for invalid (zero quantity) items that are linked in
- if (!is_valid_item( mitm[obj] ))
- {
- snprintf( info, INFO_SIZE, "Linked invalid item at (%d,%d)!", x, y);
- mpr( info, MSGCH_WARN );
- item_name( mitm[obj], DESC_PLAIN, name );
- dump_item( name, obj, mitm[obj] );
- }
-
- // Check that item knows what stack it's in
- if (mitm[obj].x != x || mitm[obj].y != y)
- {
- snprintf( info, INFO_SIZE, "Item position incorrect at (%d,%d)!", x, y);
- mpr( info, MSGCH_WARN );
- item_name( mitm[obj], DESC_PLAIN, name );
- dump_item( name, obj, mitm[obj] );
- }
-
- // If we run into a premarked item we're in real trouble,
- // this will also keep this from being an infinite loop.
- if (mitm[obj].flags & ISFLAG_DEBUG_MARK)
- {
- snprintf( info, INFO_SIZE, "Potential INFINITE STACK at (%d, %d)", x, y);
- mpr( info, MSGCH_WARN );
- break;
- }
-
- mitm[obj].flags |= ISFLAG_DEBUG_MARK;
- }
- }
- }
-
- // Now scan all the items on the level:
- for (i = 0; i < MAX_ITEMS; i++)
- {
- if (!is_valid_item( mitm[i] ))
- continue;
-
- item_name( mitm[i], DESC_PLAIN, name );
-
- // Don't check (-1,-1) player items or (0,0) monster items
- if ((mitm[i].x > 0 || mitm[i].y > 0)
- && !(mitm[i].flags & ISFLAG_DEBUG_MARK))
- {
- mpr( "Unlinked item:", MSGCH_WARN );
- dump_item( name, i, mitm[i] );
-
- snprintf( info, INFO_SIZE, "igrd(%d,%d) = %d", mitm[i].x, mitm[i].y,
- igrd[ mitm[i].x ][ mitm[i].y ] );
- mpr( info );
-
- // Let's check to see if it's an errant monster object:
- for (int j = 0; j < MAX_MONSTERS; j++)
- {
- for (int k = 0; k < NUM_MONSTER_SLOTS; k++)
- {
- if (menv[j].inv[k] == i)
- {
- snprintf( info, INFO_SIZE, "Held by monster #%d: %s at (%d,%d)",
- j, ptr_monam( &menv[j], DESC_CAP_A ),
- menv[j].x, menv[j].y );
-
- mpr( info );
- }
- }
- }
- }
-
- // Current bad items of interest:
- // -- armour and weapons with large enchantments/illegal special vals
- //
- // -- items described as questionable (the class 100 bug)
- //
- // -- eggplant is an illegal throwing weapon
- //
- // -- bola is an illegal fixed artefact
- //
- // -- items described as buggy (typically adjectives out of range)
- // (note: covers buggy, bugginess, buggily, whatever else)
- //
- if (strstr( name, "questionable" ) != NULL
- || strstr( name, "eggplant" ) != NULL
- || strstr( name, "bola" ) != NULL
- || strstr( name, "bugg" ) != NULL)
- {
- mpr( "Bad item:", MSGCH_WARN );
- dump_item( name, i, mitm[i] );
- }
- else if ((mitm[i].base_type == OBJ_WEAPONS
- && (abs(mitm[i].plus) > 30
- || abs(mitm[i].plus2) > 30
- || (!is_random_artefact( mitm[i] )
- && (mitm[i].special >= 30
- && mitm[i].special < 181))))
-
- || (mitm[i].base_type == OBJ_MISSILES
- && (abs(mitm[i].plus) > 25
- || (!is_random_artefact( mitm[i] )
- && mitm[i].special >= 30)))
-
- || (mitm[i].base_type == OBJ_ARMOUR
- && (abs(mitm[i].plus) > 25
- || (!is_random_artefact( mitm[i] )
- && mitm[i].sub_type != ARM_HELMET
- && mitm[i].special >= 30))))
- {
- mpr( "Bad plus or special value:", MSGCH_WARN );
- dump_item( name, i, mitm[i] );
- }
- }
-
- // Don't want debugging marks interfering with anything else.
- for (i = 0; i < MAX_ITEMS; i++)
- mitm[i].flags &= (~ISFLAG_DEBUG_MARK);
-
- // Quickly scan monsters for "program bug"s.
- for (i = 0; i < MAX_MONSTERS; i++)
- {
- const struct monsters *const monster = &menv[i];
-
- if (monster->type == -1)
- continue;
-
- moname( monster->type, true, DESC_PLAIN, name );
-
- if (strcmp( name, "program bug" ) == 0)
- {
- mpr( "Program bug detected!", MSGCH_WARN );
-
- snprintf( info, INFO_SIZE,
- "Buggy monster detected: monster #%d; position (%d,%d)",
- i, monster->x, monster->y );
-
- mpr( info, MSGCH_WARN );
- }
- }
-}
-#endif
-
-//---------------------------------------------------------------
-//
-// debug_add_skills
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-void debug_add_skills(void)
-{
- int skill = debug_prompt_for_skill( "Which skill (by name)? " );
-
- if (skill == -1)
- mpr("That skill doesn't seem to exist.");
- else
- {
- mpr("Exercising...");
- exercise(skill, 100);
- }
-} // end debug_add_skills()
-#endif
-
-//---------------------------------------------------------------
-//
-// debug_set_skills
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-void debug_set_skills(void)
-{
- int skill = debug_prompt_for_skill( "Which skill (by name)? " );
-
- if (skill == -1)
- mpr("That skill doesn't seem to exist.");
- else
- {
- mpr( skill_name(skill) );
- int amount = debug_prompt_for_int( "To what level? ", true );
-
- if (amount == -1)
- canned_msg( MSG_OK );
- else
- {
- const int points = (skill_exp_needed( amount + 1 )
- * species_skills( skill, you.species )) / 100;
-
- you.skill_points[skill] = points + 1;
- you.skills[skill] = amount;
-
- calc_total_skill_points();
-
- redraw_skill( you.your_name, player_title() );
-
- switch (skill)
- {
- case SK_FIGHTING:
- calc_hp();
- break;
-
- case SK_SPELLCASTING:
- case SK_INVOCATIONS:
- case SK_EVOCATIONS:
- calc_mp();
- break;
-
- case SK_DODGING:
- you.redraw_evasion = 1;
- break;
-
- case SK_ARMOUR:
- you.redraw_armour_class = 1;
- you.redraw_evasion = 1;
- break;
-
- default:
- break;
- }
- }
- }
-} // end debug_add_skills()
-#endif
-
-
-//---------------------------------------------------------------
-//
-// debug_set_all_skills
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-void debug_set_all_skills(void)
-{
- int i;
- int amount = debug_prompt_for_int( "Set all skills to what level? ", true );
-
- if (amount < 0) // cancel returns -1 -- bwr
- canned_msg( MSG_OK );
- else
- {
- if (amount > 27)
- amount = 27;
-
- for (i = SK_FIGHTING; i < NUM_SKILLS; i++)
- {
- if (i == SK_UNUSED_1
- || (i > SK_UNARMED_COMBAT && i < SK_SPELLCASTING))
- {
- continue;
- }
-
- const int points = (skill_exp_needed( amount + 1 )
- * species_skills( i, you.species )) / 100;
-
- you.skill_points[i] = points + 1;
- you.skills[i] = amount;
- }
-
- redraw_skill( you.your_name, player_title() );
-
- calc_total_skill_points();
-
- calc_hp();
- calc_mp();
-
- you.redraw_armour_class = 1;
- you.redraw_evasion = 1;
- }
-} // end debug_add_skills()
-#endif
-
-
-//---------------------------------------------------------------
-//
-// debug_add_mutation
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-bool debug_add_mutation(void)
-{
- bool success = false;
- char specs[80];
-
- // Yeah, the gaining message isn't too good for this... but
- // there isn't an array of simple mutation names. -- bwr
- mpr( "Which mutation (by message when getting mutation)? ", MSGCH_PROMPT );
- get_input_line( specs, sizeof( specs ) );
-
- if (specs[0] == '\0')
- return (false);
-
- int mutation = -1;
-
- for (int i = 0; i < NUM_MUTATIONS; i++)
- {
- char mut_name[80];
- strncpy( mut_name, mutation_name( i, 1 ), sizeof( mut_name ) );
-
- char *ptr = strstr( strlwr(mut_name), strlwr(specs) );
- if (ptr != NULL)
- {
- // we take the first mutation that matches
- mutation = i;
- break;
- }
- }
-
- if (mutation == -1)
- mpr("I can't warp you that way!");
- else
- {
- snprintf( info, INFO_SIZE, "Found: %s", mutation_name( mutation, 1 ) );
- mpr( info );
-
- int levels = debug_prompt_for_int( "How many levels? ", false );
-
- if (levels == 0)
- {
- canned_msg( MSG_OK );
- success = false;
- }
- else if (levels > 0)
- {
- for (int i = 0; i < levels; i++)
- {
- if (mutate( mutation ))
- success = true;
- }
- }
- else
- {
- for (int i = 0; i < -levels; i++)
- {
- if (delete_mutation( mutation ))
- success = true;
- }
- }
- }
-
- return (success);
-} // end debug_add_mutation()
-#endif
-
-
-//---------------------------------------------------------------
-//
-// debug_get_religion
-//
-//---------------------------------------------------------------
-#ifdef WIZARD
-void debug_get_religion(void)
-{
- char specs[80];
-
- mpr( "Which god (by name)? ", MSGCH_PROMPT );
- get_input_line( specs, sizeof( specs ) );
-
- if (specs[0] == '\0')
- return;
-
- int god = -1;
-
- for (int i = 1; i < NUM_GODS; i++)
- {
- char name[80];
- strncpy( name, god_name(i), sizeof( name ) );
-
- char *ptr = strstr( strlwr(name), strlwr(specs) );
- if (ptr != NULL)
- {
- god = i;
- break;
- }
- }
-
- if (god == -1)
- mpr( "That god doesn't seem to be taking followers today." );
- else
- {
- grd[you.x_pos][you.y_pos] = 179 + god;
- god_pitch(god);
- }
-} // end debug_add_skills()
-#endif
-
-
-void error_message_to_player(void)
-{
- mpr("Oh dear. There appears to be a bug in the program.");
- mpr("I suggest you leave this level then save as soon as possible.");
-
-} // end error_message_to_player()
-
-#ifdef WIZARD
-
-static int create_fsim_monster(int mtype, int hp)
-{
- const int mi =
- create_monster( mtype, 0, BEH_HOSTILE, you.x_pos, you.y_pos,
- MHITNOT, 250 );
-
- if (mi == -1)
- return (mi);
-
- monsters *mon = &menv[mi];
- mon->hit_points = mon->max_hit_points = hp;
- return (mi);
-}
-
-static skill_type fsim_melee_skill(const item_def *item)
-{
- skill_type sk = SK_UNARMED_COMBAT;
- if (item)
- sk = weapon_skill(*item);
- return (sk);
-}
-
-static void fsim_set_melee_skill(int skill, const item_def *item)
-{
- you.skills[fsim_melee_skill(item)] = skill;
- you.skills[SK_FIGHTING] = skill * 15 / 27;
-}
-
-static void fsim_set_ranged_skill(int skill, const item_def *item)
-{
- you.skills[range_skill(*item)] = skill;
- you.skills[SK_RANGED_COMBAT] = skill * 15 / 27;
-}
-
-static void fsim_item(FILE *out,
- bool melee,
- const item_def *weap,
- int wskill, unsigned long damage,
- long iterations, long hits,
- int maxdam, unsigned long time)
-{
- double hitdam = hits? double(damage) / hits : 0.0;
- int avspeed = (int) (time / iterations);
- fprintf(out, " %2d | %3ld%% | %5.2f | %5.2f | %5.2f | %3d | %2ld\n",
- wskill,
- 100 * hits / iterations,
- double(damage) / iterations,
- hitdam,
- double(damage) * player_speed() / avspeed / iterations,
- maxdam,
- time / iterations);
-}
-
-static bool fsim_ranged_combat(FILE *out, int wskill, int mi,
- const item_def *item, int missile_slot)
-{
- monsters &mon = menv[mi];
- unsigned long cumulative_damage = 0L;
- unsigned long time_taken = 0L;
- long hits = 0L;
- int maxdam = 0;
-
- const int thrown = missile_slot == -1? get_fire_item_index() : missile_slot;
- if (thrown == ENDOFPACK || thrown == -1)
- {
- mprf("No suitable missiles for combat simulation.");
- return (false);
- }
-
- fsim_set_ranged_skill(wskill, item);
-
- no_messages mx;
- const long iter_limit = Options.fsim_rounds;
- const int hunger = you.hunger;
- for (long i = 0; i < iter_limit; ++i)
- {
- mon.hit_points = mon.max_hit_points;
- bolt beam;
- you.time_taken = player_speed();
- if (throw_it(beam, thrown, &mon))
- hits++;
- you.hunger = hunger;
- time_taken += you.time_taken;
-
- int damage = (mon.max_hit_points - mon.hit_points);
- cumulative_damage += damage;
- if (damage > maxdam)
- maxdam = damage;
- }
- fsim_item(out, false, item, wskill, cumulative_damage,
- iter_limit, hits, maxdam, time_taken);
-
- return (true);
-}
-
-static bool fsim_melee_combat(FILE *out, int wskill, int mi,
- const item_def *item)
-{
- monsters &mon = menv[mi];
- unsigned long cumulative_damage = 0L;
- unsigned long time_taken = 0L;
- long hits = 0L;
- int maxdam = 0;
-
- fsim_set_melee_skill(wskill, item);
-
- no_messages mx;
- const long iter_limit = Options.fsim_rounds;
- const int hunger = you.hunger;
- for (long i = 0; i < iter_limit; ++i)
- {
- mon.hit_points = mon.max_hit_points;
- you.time_taken = player_speed();
- if (you_attack(mi, true))
- hits++;
-
- you.hunger = hunger;
- time_taken += you.time_taken;
-
- int damage = (mon.max_hit_points - mon.hit_points);
- cumulative_damage += damage;
- if (damage > maxdam)
- maxdam = damage;
- }
- fsim_item(out, true, item, wskill, cumulative_damage, iter_limit, hits,
- maxdam, time_taken);
-
- return (true);
-}
-
-static bool debug_fight_simulate(FILE *out, int wskill, int mi, int miss_slot)
-{
- int weapon = you.equip[EQ_WEAPON];
- const item_def *iweap = weapon != -1? &you.inv[weapon] : NULL;
-
- if (iweap && iweap->base_type == OBJ_WEAPONS
- && is_range_weapon(*iweap))
- return fsim_ranged_combat(out, wskill, mi, iweap, miss_slot);
- else
- return fsim_melee_combat(out, wskill, mi, iweap);
-}
-
-static const item_def *fsim_weap_item()
-{
- const int weap = you.equip[EQ_WEAPON];
- if (weap == -1)
- return NULL;
-
- return &you.inv[weap];
-}
-
-static std::string fsim_wskill()
-{
- const item_def *iweap = fsim_weap_item();
- return iweap && iweap->base_type == OBJ_WEAPONS
- && is_range_weapon(*iweap)?
- skill_name( range_skill(*iweap) ) :
- iweap? skill_name( fsim_melee_skill(iweap) ) :
- skill_name( SK_UNARMED_COMBAT );
-}
-
-static std::string fsim_weapon(int missile_slot)
-{
- char item_buf[ITEMNAME_SIZE];
- if (you.equip[EQ_WEAPON] != -1)
- {
- const item_def &weapon = you.inv[ you.equip[EQ_WEAPON] ];
- item_name(weapon, DESC_PLAIN, item_buf, true);
-
- if (is_range_weapon(weapon))
- {
- const int missile =
- missile_slot == -1? get_fire_item_index() :
- missile_slot;
- if (missile < ENDOFPACK)
- {
- std::string base = item_buf;
- base += " with ";
- in_name(missile, DESC_PLAIN, item_buf, true);
- return (base + item_buf);
- }
- }
- }
- else
- {
- strncpy(item_buf, "unarmed", sizeof item_buf);
- }
- return (item_buf);
-}
-
-static std::string fsim_time_string()
-{
- time_t curr_time = time(NULL);
- struct tm *ltime = localtime(&curr_time);
- if (ltime)
- {
- char buf[100];
- snprintf(buf, sizeof buf, "%4d%02d%02d/%2d:%02d:%02d",
- ltime->tm_year + 1900,
- ltime->tm_mon + 1,
- ltime->tm_mday,
- ltime->tm_hour,
- ltime->tm_min,
- ltime->tm_sec);
- return (buf);
- }
- return ("");
-}
-
-static void fsim_mon_stats(FILE *o, const monsters &mon)
-{
- char buf[ITEMNAME_SIZE];
- fprintf(o, "Monster : %s\n",
- moname(mon.type, true, DESC_PLAIN, buf));
- fprintf(o, "HD : %d\n", mon.hit_dice);
- fprintf(o, "AC : %d\n", mon.armour_class);
- fprintf(o, "EV : %d\n", mon.evasion);
-}
-
-static void fsim_title(FILE *o, int mon, int ms)
-{
- char buf[ITEMNAME_SIZE];
- fprintf(o, "Dungeon Crawl Stone Soup version " VERSION "\n\n");
- fprintf(o, "Combat simulation: %s %s vs. %s (%ld rounds) (%s)\n",
- species_name(you.species, you.experience_level),
- you.class_name,
- moname(menv[mon].type, true, DESC_PLAIN, buf),
- Options.fsim_rounds,
- fsim_time_string().c_str());
- fprintf(o, "Experience: %d\n", you.experience_level);
- fprintf(o, "Strength : %d\n", you.strength);
- fprintf(o, "Intel. : %d\n", you.intel);
- fprintf(o, "Dexterity : %d\n", you.dex);
- fprintf(o, "Base speed: %d\n", player_speed());
- fprintf(o, "\n");
- fsim_mon_stats(o, menv[mon]);
- fprintf(o, "\n");
- fprintf(o, "Weapon : %s\n", fsim_weapon(ms).c_str());
- fprintf(o, "Skill : %s\n", fsim_wskill().c_str());
- fprintf(o, "\n");
- fprintf(o, "Skill | Accuracy | Av.Dam | Av.HitDam | Eff.Dam | Max.Dam | Av.Time\n");
-}
-
-static int fsim_stat(int stat)
-{
- return (stat < 1 ? 1 :
- stat > 60 ? 60 :
- stat);
-}
-
-static bool debug_fight_sim(int mindex, int missile_slot)
-{
- FILE *ostat = fopen("fight.stat", "a");
- if (!ostat)
- {
- mprf("Can't write fight.stat: %s", strerror(errno));
- return (false);
- }
-
- bool success = true;
- FixedVector<unsigned char, 50> skill_backup = you.skills;
- int ystr = you.strength,
- yint = you.intel,
- ydex = you.dex;
- int yxp = you.experience_level;
-
- for (int i = SK_FIGHTING; i < NUM_SKILLS; ++i)
- you.skills[i] = 0;
-
- you.experience_level = Options.fsim_xl;
- if (you.experience_level < 1)
- you.experience_level = 1;
- if (you.experience_level > 27)
- you.experience_level = 27;
-
- you.strength = fsim_stat(Options.fsim_str);
- you.intel = fsim_stat(Options.fsim_int);
- you.dex = fsim_stat(Options.fsim_dex);
-
- fsim_title(ostat, mindex, missile_slot);
- for (int wskill = 0; wskill <= 27; ++wskill)
- {
- mesclr();
- mprf("Calculating average damage for %s at skill %d",
- fsim_weapon(missile_slot).c_str(), wskill);
- if (!debug_fight_simulate(ostat, wskill, mindex, missile_slot))
- goto done_combat_sim;
-
- fflush(ostat);
- // Not checking in the combat loop itself; that would be more responsive
- // for the user, but slow down the sim with all the calls to kbhit().
- if (kbhit() && getch() == 27)
- {
- success = false;
- mprf("Canceling simulation\n");
- goto done_combat_sim;
- }
- }
- you.skills = skill_backup;
- you.strength = ystr;
- you.intel = yint;
- you.dex = ydex;
- you.experience_level = yxp;
-
- mprf("Done fight simulation with %s", fsim_weapon(missile_slot).c_str());
-
-done_combat_sim:
- fprintf(ostat, "-----------------------------------\n\n");
- fclose(ostat);
-
- return (success);
-}
-
-int fsim_kit_equip(const std::string &kit)
-{
- int missile_slot = -1;
- char item_buf[ITEMNAME_SIZE];
-
- std::string::size_type ammo_div = kit.find("/");
- std::string weapon = kit;
- std::string missile;
- if (ammo_div != std::string::npos)
- {
- weapon = kit.substr(0, ammo_div);
- missile = kit.substr(ammo_div + 1);
- trim_string(weapon);
- trim_string(missile);
- }
-
- for (int i = 0; i < ENDOFPACK; ++i)
- {
- if (!is_valid_item(you.inv[i]))
- continue;
-
- in_name(i, DESC_PLAIN, item_buf, true);
- if (std::string(item_buf).find(weapon) != std::string::npos)
- {
- if (i != you.equip[EQ_WEAPON])
- {
- wield_weapon(true, i, false);
- if (i != you.equip[EQ_WEAPON])
- return -100;
- }
- break;
- }
- }
-
- if (!missile.empty())
- {
- for (int i = 0; i < ENDOFPACK; ++i)
- {
- if (!is_valid_item(you.inv[i]))
- continue;
-
- in_name(i, DESC_PLAIN, item_buf, true);
- if (std::string(item_buf).find(missile) != std::string::npos)
- {
- missile_slot = i;
- break;
- }
- }
- }
-
- return (missile_slot);
-}
-
-// Writes statistics about a fight to fight.stat in the current directory.
-// For fight purposes, a punching bag is summoned and given lots of hp, and the
-// average damage the player does to the p. bag over 10000 hits is noted,
-// advancing the weapon skill from 0 to 27, and keeping fighting skill to 2/5
-// of current weapon skill.
-void debug_fight_statistics(bool use_defaults)
-{
- int punching_bag = get_monnum(Options.fsim_mons.c_str());
- if (punching_bag == -1)
- punching_bag = MONS_WORM;
-
- int mindex = create_fsim_monster(punching_bag, 500);
- if (mindex == -1)
- {
- mprf("Failed to create punching bag");
- return;
- }
-
- if (!use_defaults)
- {
- debug_fight_sim(mindex, -1);
- goto fsim_mcleanup;
- }
-
- for (int i = 0, size = Options.fsim_kit.size(); i < size; ++i)
- {
- int missile = fsim_kit_equip(Options.fsim_kit[i]);
- if (missile == -100)
- {
- mprf("Aborting sim on %s", Options.fsim_kit[i].c_str());
- goto fsim_mcleanup;
- }
- if (!debug_fight_sim(mindex, missile))
- break;
- }
-fsim_mcleanup:
- monster_die(&menv[mindex], KILL_DISMISSED, 0);
-}
-#endif